Dynamic Columns
A common grid requirement is a possibility to configure visible columns.
Note: this cannot be achieved using columns property, since columns property is not bindable.
One way of doing this is by using ContentResolver.
ContentResolver would listen to the changes of some store, i.e. visibleColumns and re-create columns array every time the store changes.
However, since grid would be re-rendered on each store change, state of the grid, i.e. scroll, column widths (if resized from the initial width) would be lost.
To avoid this, columnParams and onGetColumns callback were introduced.
Visible Columns:
| Name | Continent | Browser | Visits |
|---|---|---|---|
| Marc Murray | South America | Edge | 2 |
| Emilie Effertz | Africa | Internet Explorer | 68 |
| Rupert Schulist | Australia | Internet Explorer | 46 |
| Jessy Feest | South America | Safari | 11 |
| Kyleigh Schroeder | Europe | Chrome | 83 |
| 5 items | 4 continents | 4 browsers | 210 |
Multi-line use case:
| Name | Continent | Browser | Visits | |
|---|---|---|---|---|
| Marc Murray | South America | Edge | 2 | |
| Emilie Effertz | Africa | Internet Explorer | 68 | |
| Rupert Schulist | Australia | Internet Explorer | 46 | |
| Jessy Feest | South America | Safari | 11 | |
| Kyleigh Schroeder | Europe | Chrome | 83 | |
| 5 items | 4 continents | 4 browsers | 210 |
<div style="margin-bottom: 10px" ws> Visible Columns: <LookupField values-bind="$page.visibleColumns" options={[ {id: 'fullName', text: 'Name'}, {id: 'continent', text: 'Continent'}, {id: 'browser', text: 'Browser'}, {id: 'visits', text: 'Visits'}, ]} multiple={true} /> </div> <Grid records-bind='$page.records' style={{width: "100%"}} columnParams-bind="$page.visibleColumns" onGetColumns={(visibleColumns) => { return allColumns.filter(c => visibleColumns.includes(c.field)); }} /> <div text="Multi-line use case:" visible-expr='{$page.visibleColumns.length}' style='margin: 20px 0' /> <Grid records-bind="$page.records" style={{width: "100%"}} columnParams-bind="$page.visibleColumns" onGetColumns={(visibleColumns) => { let columns = allColumns.filter(c => visibleColumns.includes(c.field)); if (!columns.length) return {}; return { style: { background: {expr: "{$record.showDescription} ? '#fff7e6' : null"} }, line1: { columns: [ ...columns, { header: false, align: "center", pad: false, items: <cx> <cx> <Button mod="hollow" icon="drop-down" onClick={(e, {store}) => { store.toggle('$record.showDescription'); }} /> </cx> </cx>, visible: columns.length > 0 } ] }, line3: { visible: {expr: "{$record.showDescription}"}, columns: [{ colSpan: 1000, style: 'border-top-color: rgba(0, 0, 0, 0.05)', items: <cx> <div> {columns.map(c => <cx> <div> <div text-tpl={`${c.header}: `} style='width: 70px; display: inline-block; text-align: right; margin-right: 10px; font-weight: bold' /> <div text-tpl={`{$record.${c.field}}`} style='display: inline-block'/> </div> </cx>)} </div> </cx> }] } } }} />