You're viewing the legacy site. Visit cxjs.io/docs for the latest documentation. Legacy site. Visit cxjs.io/docs for new docs.

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
Jarred Murphy
477-257-7708MaxhavenNo
Ofelia Koch
709-200-3714East KatlynnNo
Dewayne Kertzmann
099-903-5956East JessicaNo
Davonte Witting
137-757-8556AntwanburghNo
Agustin Wolff
365-567-5153New ZoeNo
Kariane Lubowitz
324-207-5678Lake GeoffreyNo
Edwardo Langworth
216-295-9774West TitusNo
Shawn Kuhn
855-469-9435WellingtonfortNo
Elmo Bednar
212-693-3565LilliansideNo
Cristian Davis
600-937-8410East DesireeNo
Nikita Hessel
338-118-5834WebertonNo
Ora Macejkovic
793-576-5282New MarionNo
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