Documentation

Report Edit

Stateful Tree Grid

The following example shows how to make a stateful tree grid component with some common tree functionalities. This way, the state (expanded folders) of the grid will be preserved, even if we reload grid data. Keep in mind that a record's state will be preserved only if the value of the record's expanded property after reload is nullish (null or undefined).

To make grid stateful, restoreExpandedNodesOnLoad property should be set to true on TreeAdapter. Additionally, keyField property on either Grid or data adapter has to be specified.

The Code also showcases usage of some builtin Cx functions for easier tree manipulation, like updateTree and removeTreeNodes.

NamePhoneCityNotified
Domenick Denesik
514-367-8991GailtownNo
Maximilian Wisozk
840-164-1103AdriennelandNo
Vladimir Walker
013-988-2001Lake BretNo
Makayla McClure
474-375-9315LaronshireNo
Stephan Weimann
430-301-5839CleosideNo
Fannie Homenick
237-302-3216East IsabelshireNo
Lesley Okuneva
070-840-6531GiuseppemouthNo
Lupe Murray
818-863-3618GermainetownNo
Oma Wunsch
288-934-0387New FaeNo
Grayson Brakus
083-671-1226LlewellyntonNo
Cierra Adams
326-786-2607GisselleburyNo
Kyla Fahey
481-972-0228JewelburyNo
NamePhoneCityNotified
ControllerIndex
<div controller={PageController}>
   <FlexRow spacing style="margin-bottom: 10px">
      <Button onClick="load" text="Reload" mod="primary" />
      <Button
         onClick="expandCollapseTree"
         text="Expand All"
         text-expr="{$page.treeExpanded} ? 'Collapse All' : 'Expand All'"
      />
      <Button onClick="addFolder" text="Add Folder" />
      <Button onClick="addLeaf" text="Add File" />
      <Button onClick="deleteRecord" text="Delete" mod="danger" disabled-expr="!{$page.selection}" />
   </FlexRow>
   <Grid
      emptyText="Loading data..."
      records-bind="$page.data"
      mod="tree"
      style={{
         width: "100%",
         opacity: expr("{$page.loading} ? 0.4 : 1"),
         height: 400,
      }}
      scrollable={true}
      dataAdapter={{
         type: TreeAdapter,
         restoreExpandedNodesOnLoad: true,
      }}
      keyField='recordId'
      selection={{ type: KeySelection, bind: "$page.selection", keyField: 'recordId' }}
      columns={[
         {
            header: "Name",
            field: "fullName",
            sortable: true,
            items: (
               <cx>
                  <TreeNode
                     expanded-bind="$record.$expanded"
                     leaf-bind="$record.$leaf"
                     level-bind="$record.$level"
                     loading-bind="$record.$loading"
                     text-bind="$record.fullName"
                     icon-bind="$record.icon"
                  />
               </cx>
            ),
         },
         { header: "Phone", field: "phone" },
         { header: "City", field: "city", sortable: true },
         {
            header: "Notified",
            field: "notified",
            sortable: true,
            value: { expr: '{$record.notified} ? "Yes" : "No"' },
         },
      ]}
      onRowContextMenu={(e, instance) => {
         openContextMenu(
            e,
            <cx>
               <Menu>
                  <MenuItem onClick="deleteRecordFromContextMenu" autoClose>
                     Delete
                  </MenuItem>
                  <PureContainer visible-expr="!{$record.$leaf}">
                     <MenuItem onClick="addFolderFromContextMenu" autoClose>
                        Add Folder
                     </MenuItem>
                     <MenuItem onClick="addLeafFromContextMenu" autoClose>
                        Add File
                     </MenuItem>
                  </PureContainer>
               </Menu>
            </cx>,
            instance
         );
      }}
   />
</div>
Copied!Cx Fiddle