Page 1 of 1

[REACT] Tree row reorder + backend synch with onDataChange

Posted: Wed Feb 01, 2023 11:58 am
by julienbuteau

Hello guys, I am considering Bryntum Grid for my next project.

Trying to implement a react tree grid with ability to move rows freely + synch backend, I am not convinced by my approach using onDataChange. Any help or implementation examples?

Thanks!

const syncData = ({ store, action, records, isExpand, isCollapse }) => {
    //console.log(`${store.id} changed. The action was: ${action}. Changed records: `, records);
    if (!isExpand && !isCollapse) {
      switch (action) {

    case 'update':
      // device field update (except parent)  
      if (!records[0].meta.modified.hasOwnProperty('parentId')) {
        const key = Object.keys(records[0].meta.modified);
        const value = records[0].data[key];
        transact([tx.devices[records[0].data.id].update({ [key]: value })]);
      }
      break;

    case 'add':
      // device parent update
      if (records[0].meta.modified.hasOwnProperty('parentId')) {
        transact([tx.devices[records[0].data.id].update({ parentId: records[0].data.parentId })]);
      }
      //TODO: manage copy-paste case for proper id generation
      break;
  }
}
  }

Re: [REACT] Tree row reorder + backend synch with onDataChange

Posted: Wed Feb 01, 2023 8:03 pm
by marcio

Hello julienbuteau,

I'm sharing an AppConfig.js file that I adapt from our React basic demo to match your case, is this what you're looking for??

/**
 * Application configuration
 */
import React from "react";
import DemoButton from "./components/DemoButton";
import DemoEditor from "./components/DemoEditor";
import { StringHelper } from "@bryntum/grid";

const syncData = ({ store, action, records, isExpand, isCollapse }) => {
//   console.log(`${store.id} changed. The action was: ${action}. Changed records: `, records);
  if (!isExpand && !isCollapse) {
    switch (action) {
      case "update":
        // device field update (except parent)
        if (!records[0].meta.modified.hasOwnProperty("parentId")) {
          const key = Object.keys(records[0].meta.modified);
          const value = records[0].data[key];
          // transact([tx.devices[records[0].data.id].update({ [key]: value })]);
        }
        break;

  case "add":
    // device parent update
    if (records[0].meta.modified.hasOwnProperty("parentId")) {
      // transact([tx.devices[records[0].data.id].update({ parentId: records[0].data.parentId })]);
    }
    //TODO: manage copy-paste case for proper id generation
    break;
  case "move":
  // handle Move event
    console.log('move event')
}
  }
};

const useGridConfig = (handleCellButtonClick) => {
  return {
    // Initial grouping, with custom group renderer
    groupFeature: {
      field: "division",
      groupRenderer(data) {
        if (data.column === data.grid.columns.first) {
          return StringHelper.xss`${data.groupColumn.text}: ${data.groupRowFor}`;
        }
        return "";
      },
    },
    features: {
      rowReorder: {
        showGrip: true,
      },
    },
    onDataChange: (eventData) => {
      syncData(eventData);
    },

columns: [
  {
    field: "team",
    text: 'Team<div class="small-text">(inline JSX)</div>',
    htmlEncodeHeaderText: false,
    flex: 1,
    // Using simple inline JSX
    renderer: ({ value }) => <b>{StringHelper.encodeHtml(value)}</b>,
  },
  { field: "city", text: "City", flex: 1 },
  {
    field: "original",
    text: 'Original<div class="small-text">(React editor)</div>',
    htmlEncodeHeaderText: false,
    align: "center",
    width: 120,
    renderer: ({ value }) => (value ? "Yes" : "No"),
    editor: (ref, instance) => <DemoEditor instance={instance} ref={ref} />,
  },
  {
    field: "division",
    text: "Division",
    flex: 1,
    hidden: true,
  },
  { field: "conference", text: "Conference", flex: 1 },
  {
    field: "team",
    text: 'Cheer<div class="small-text">(React component)</div>',
    htmlEncodeHeaderText: false,
    width: 200,
    editor: false,
    // Using custom React component
    renderer: ({ record }) => (
      <DemoButton
        text={`Go ${StringHelper.encodeHtml(record.team)}!`}
        onClick={() => handleCellButtonClick(record)}
      />
    ),
  },
],

// Store will be created automatically, `syncDataOnLoad` is `true` by default (set in the wrapper)
data: [
  {
    id: 1,
    team: "Capitals",
    city: "Washington",
    division: "Metropolitan",
    conference: "Eastern",
    original: false,
  },
  {
    id: 2,
    team: "Penguins",
    city: "Pittsburgh",
    division: "Metropolitan",
    conference: "Eastern",
    original: false,
  },
  {
    id: 3,
    team: "Rangers",
    city: "New York",
    division: "Metropolitan",
    conference: "Eastern",
    original: false,
  },
  {
    id: 4,
    team: "Lightning",
    city: "Tampa Bay",
    division: "Atlantic",
    conference: "Eastern",
    original: false,
  },
  {
    id: 5,
    team: "Maple Leafs",
    city: "Toronto",
    division: "Atlantic",
    conference: "Eastern",
    original: true,
  },
  {
    id: 6,
    team: "Red Wings",
    city: "Detroit",
    division: "Atlantic",
    conference: "Eastern",
    original: true,
  },
  {
    id: 7,
    team: "Ducks",
    city: "Anaheim",
    division: "Pacific",
    conference: "Western",
    original: false,
  },
  {
    id: 8,
    team: "Sharks",
    city: "San Jose",
    division: "Pacific",
    conference: "Western",
    original: false,
  },
  {
    id: 9,
    team: "Golden Knights",
    city: "Las Vegas",
    division: "Pacific",
    conference: "Western",
    original: false,
  },
  {
    id: 10,
    team: "Predators",
    city: "Nashville",
    division: "Central",
    conference: "Western",
    original: false,
  },
  {
    id: 11,
    team: "Jets",
    city: "Winnipeg",
    division: "Central",
    conference: "Western",
    original: false,
  },
  {
    id: 12,
    team: "Avalanche",
    city: "Colorado",
    division: "Central",
    conference: "Western",
    original: false,
  },
],
  };
};

const rowHeightConfig = {
  label: "Row Height:",
  labelWidth: 90,
  flex: "0 0 178px",
  min: 40,
  max: 100,
  step: 1,
};

export { useGridConfig, rowHeightConfig };

Re: [REACT] Tree row reorder + backend synch with onDataChange

Posted: Wed Feb 01, 2023 9:35 pm
by julienbuteau

Hey marcio, thank you for the prompt reply. I think I managed to solve it in the end, but had trouble navigating the doc. Here's my path, from react examples to store CRUD features :)

https://bryntum.com/products/grid/docs/guide/Grid/integration/react/events

You can find details of all events that are fired by BryntumGrid in the:

https://bryntum.com/products/grid/docs/api/Grid/view/Grid#events

See the store change event documentation for more information:

https://bryntum.com/products/grid/docs/api/Core/data/Store#event-change

A more complex databound widget such as a grid may use the more granular events...

https://bryntum.com/products/grid/docs/api/Core/data/mixin/StoreCRUD#events


Re: [REACT] Tree row reorder + backend synch with onDataChange

Posted: Wed Feb 01, 2023 9:52 pm
by marcio

Great to hear that julien! :D

We're always looking for improving our docs to make them easier to navigate.

Feel free to ask us if you need any help during your development with Bryntum!