AgGridReact - Grid does not update when isRowSelectable changes
Asked Answered
C

4

8

I am trying to pass isRowSelectable dynamically as a prop to an AgGridReact. In the following toy example, You expect that clicking the "Switch criteria" button will change the set of items in the grid that have checkboxes. Instead, the grid is unchanged.

Screenshots:

interface Item { name: string, age: number, height: number}
const data: Item[] = [
    {name: "old and tall", age: 80, height: 80}, 
    {name: "old and short", age: 80, height: 20},
    {name: "young and tall", age: 10, height: 80}, 
    {name: "young and short", age: 10, height: 20}, 
]
const colDefs: ColDef[] = [
    {
        headerName: "",
        checkboxSelection: true,
        headerCheckboxSelection: true,
        headerCheckboxSelectionFilteredOnly: true,
        width: 60,
        sortable: false
    },
    { field: "name"},
    { field: "age"},
    { field: "height"}
]

const criteria1 = (node: RowNode) => node.data.age > 50
const criteria2 = (node: RowNode) => node.data.height > 50

export const DevPage: FunctionComponent = () => {

    const [isCriteria1, setIsCriteria1] = useState<boolean>(false)

    return ( <Fragment>
    
        <h2> {isCriteria1 ? "By Age" : "By Height"} </h2>
        <Button onClick = { () => setIsCriteria1(!isCriteria1) }> 
            Switch criteria
        </Button> 
        
        <div className="ag-theme-alpine" style={{height:"800px"}}>
            <AgGridReact
                rowSelection="multiple"
                columnDefs = {colDefs}
                rowData={data}
                isRowSelectable = {isCriteria1 ? criteria1 : criteria2}
                suppressRowClickSelection={true}
            />
        </div>
        
    </Fragment> )
}
Cartouche answered 22/9, 2020 at 17:23 Comment(0)
O
4

As a workaround, you can force all RowNodes to re-evaluate selectable property when onClick event fires.

const [rowData, setRowData] = React.useState<RowDataType[]>([]);
const criterial = React.useRef(true);
const isSelectable = (rowNode: RowNode) => {
  const result = rowNode.data.age > 25;
  const selectable = result === criterial.current;

  return selectable;
};
const toggleCriteria = () => {
  const updateSelectable = (rowNode: RowNode) => {
    rowNode.setRowSelectable(isSelectable(rowNode));
  };

  criterial.current = !criterial.current;
  gridApi.deselectAll();
  gridApi.forEachNodeAfterFilterAndSort(updateSelectable);
};

return (
  <>
    <button onClick={toggleCriteria}>Toggle Criteria</button>
    <AgGridReact
      rowSelection="multiple"
      suppressRowClickSelection
      columnDefs={columnDefs}
      onGridReady={onGridReady}
      isRowSelectable={isSelectable}
      rowData={rowData}
    />
  </>
);

Live Demo

Edit 64014770/aggridreact-grid-does-not-update-when-isrowselectable-changes/

Oogenesis answered 23/9, 2020 at 8:8 Comment(2)
Thanks! The only issue here is that this requires us to know when the prop changes. In the toy example, a button switches the criteria. In the real code it's just a prop that can change for a variety of reasons. I suppose I can make this work with a useEffect on the prop.Cartouche
Been 3 years and I wonder why they never fixed it?Ingrate
H
1

This is the AG Grid issue. The AG Grid (tested with 28.2.1) is not refreshing state when an isRowSelectable function is changed.

You can force set row selectable by the setRowSelectable function

apiRef.current?.grid?.forEachNode(
  (rowNode: RowNode) => rowNode.setRowSelectable(isSelectable(rowNode))
)

Below a fork of the NearHuscarl approach with declared react dependencies on the useCallback and the useState functions.

const [rowData, setRowData] = React.useState<Athlete[]>([]);
const [criterial, setCriteria] = React.useState(true);
const isSelectable = React.useCallback((rowNode: RowNode) => {
  const result = rowNode.data.age > 25;
  const selectable = result === criterial;
  return selectable;
}, [criterial]);
const toggleCriteria = React.useCallback(() => {
  setCriteria((c) => !c);
}, []);
React.useEffect(() => {
  apiRef.current?.grid?.deselectAll();
  apiRef.current?.grid?.forEachNode(
    (rowNode: RowNode) => rowNode.setRowSelectable(isSelectable(rowNode))
  )
}, [apiRef, isSelectable]);

return (
  <>
    <button onClick={toggleCriteria}>Toggle Criteria</button>
    <AgGridReact
      rowSelection="multiple"
      suppressRowClickSelection
      columnDefs={columnDefs}
      onGridReady={onGridReady}
      isRowSelectable={isSelectable}
      rowData={rowData}
    />
  </>
);

Live Demo

enter link description here

Humidistat answered 19/12, 2022 at 21:40 Comment(0)
G
0

we can use gridParams.api.forEachNode() to get each row node and then we can able to set checkbox select enable/disable option using setRowSelectable() method in the following way.

gridParams.api.forEachNode(node => {
    node.setRowSelectable(true) // this will enable checkbox select option 
    node.setRowSelectable(false) // this will disable checkbox select option
})
Group answered 6/12, 2023 at 10:49 Comment(0)
B
0

This was fixed in November 2023 as part of [email protected]. Check the changelog under https://github.com/ag-grid/ag-grid/releases/tag/v31.0.0, issue AG-7980.

Boarder answered 11/7 at 12:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.