olifolkerd / tabulator

Interactive Tables and Data Grids for JavaScript
http://tabulator.info
MIT License
6.59k stars 811 forks source link

Preserve group show/hide state when calling replaceData #4537

Open guilhemmarchand opened 2 months ago

guilhemmarchand commented 2 months ago

*Is your feature request related to a problem? Please describe.**

To refresh data, we call table.replaceData(); so that Tabulator handles the data refesh notably at the ajax level, which works great. However, this method does not preserve the current status of opened or closed group, and systematically re-opens any previously closed group. (which is the default behaviour unless asked otherwise)

Describe the solution you'd like

It would be great either that replaceData() automatically preserves the current state of the groups, or an option within the function or a supported method to manage the state of a group.

Describe alternatives you've considered

We have tried the following, which works BUT only for the first row of the table, this doesn't work for any other row of the table.

function getGroupState(table) {
        let groupState = {};
        let groups = table.getGroups();

        groups.forEach((group) => {
          let key = group.getField() + "_" + group.getKey();
          let element = group.getElement();

          // Check for the presence of 'tabulator-group-visible' to determine if the group is open
          let isOpen = element.classList.contains("tabulator-group-visible");

          groupState[key] = isOpen;
        });

        return groupState;
      }

      function restoreGroupState(table, groupState) {
        let groups = table.getGroups();

        groups.forEach((group) => {
          let key = group.getField() + "_" + group.getKey();

          if (groupState[key]) {
            console.log(`Restoring group ${key} to open`);
            group.show();
          } else {
            console.log(`Restoring group ${key} to closed`);
            group.hide();
          }

        });
      }

Then when calling replaceData():

// refresh data
let groupState = getGroupState(table); // Save current group state
table
  .replaceData()
  .then(() => {
    restoreGroupState(table, groupState); // Restore group state
  })
  .catch((error) => {
    console.error("Error replacing data:", error);
  });

console log messages show that we detect properly the state of the group, but opening/hidding doesn't work however.

Additional context

Version: Tabulator v6.2.1

Thank you!

rframil commented 3 weeks ago

I don't know if it'd be a good solution in your case, since it doesn't handle ajax automatically, but have you tried reactivity instead of replaceData? I discovered reactivity while trying to solve this problem (with dataTree instead of groups), thinking of storing the open/closed state within the table itself. It turns out storing the state isn't even necessary; unlike replaceData, reactivity will not change the state.