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
Michel Stiedemann
682-638-5718New JeromyNo
Roberta Pouros
161-050-4928New ErnestNo
Okey Bartoletti
059-998-7726South CarmellaNo
Ismael Nader
008-346-1512OkunevaportNo
Melvin Harber
396-196-0391New EddNo
Darwin Ferry
712-201-0627LangoshburghNo
Wilber Hessel
616-955-4326JamarcusburyNo
Abbey Stamm
160-986-8435South EnriqueNo
Elwin Olson
782-607-3148South FrancescaNo
Lavinia Huels
987-563-9445AureliotonNo
Adell Crona
206-583-6983Lake JaydonportNo
Ivory Kirlin
451-829-3724SammymouthNo
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