react table select rows - programmatically select rows based on input props

I have created a react table with select rows following this example. I'm trying to modify it so that when the data loads, the corresponding checkbox is either checked or unchecked based on the row data's included value. The value doesn't seem to be recognized and when I check/uncheck a row the onChange console.log event isn't being fired. What am I doing wrong.

Heres my Sandbox Example

DATA

[
  {
    systemId: 13,
    deqId: "25007",
    facilityId: 6487,
    sourceId: "WS002",
    sourceName: "GROVE SPRING",
    flowRate: 461,
    flowUom: "GPM   ",
    included: true
  },
  {
    systemId: 13,
    deqId: "25007",
    facilityId: 4742,
    sourceId: "WS004",
    sourceName: "WELL #1",
    flowRate: 1100,
    flowUom: "GPM   ",
    included: true
  },
  {
    systemId: 13,
    deqId: "25007",
    facilityId: 4743,
    sourceId: "WS005",
    sourceName: "100 W (WELL #2)                         ",
    flowRate: 800,
    flowUom: "GPM   ",
    included: true
  },
  {
    systemId: 13,
    deqId: "25007",
    facilityId: 4744,
    sourceId: "WS007",
    sourceName: "NORTH (WELL #3)                         ",
    flowRate: 900,
    flowUom: "GPM   ",
    included: true
  }
];

INDETERMINATE CHECKBOX

const IndeterminateCheckbox = React.forwardRef(
  ({ indeterminate, checked, name, ...rest }, ref) => {
    const defaultRef = React.useRef(checked);
    const resolvedRef = ref || defaultRef;

    React.useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate;
      resolvedRef.current.checked = checked;
    }, [resolvedRef, indeterminate, checked]);

    return (
      <>
        <input
          type="checkbox"
          ref={resolvedRef}
          checked={checked}
          name={name}
          id={name}
          {...rest}
        />
      </>
    );
  }
);

REACT TABLE


function ReactTable({
  columns,
  data,
  handleCheckboxSelection,
  handleCheckboxStateChange
}) {
  // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    footerGroups,
    rows,
    prepareRow,
    selectedFlatRows
  } = useTable(
    {
      columns,
      data
    },
    useRowSelect,
    (hooks) => {
      hooks.visibleColumns.push((columns) => [
        // Let's make a column for selection
        {
          id: "selection",
          // The header can use the table's getToggleAllRowsSelectedProps method
          // to render a checkbox
          Header: (
            { getToggleAllRowsSelectedProps },
            handleCheckboxStateChange
          ) => (
            <div>
              <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
            </div>
          ),
          // The cell can use the individual row's getToggleRowSelectedProps method
          // to the render a checkbox
          Cell: ({ row }) => (
            <div>
              <IndeterminateCheckbox
                name={row.original.sourceId}
                onChange={(row) => console.log(row.original)} //not firing
                checked={row.original.included}
                {...row.getToggleRowSelectedProps()}
              />
            </div>
          )
        },
        ...columns
      ]);
    }
  );

  // Render the UI for your table
  return (
    <>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps()}>{column.render("Header")}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.slice(0, 10).map((row, i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
        <tfoot>
          {footerGroups.map((group) => (
            <tr {...group.getFooterGroupProps()}>
              {group.headers.map((column) => (
                <td {...column.getFooterProps()}>
                  <b>{column.render("Footer")}</b>
                </td>
              ))}
            </tr>
          ))}
        </tfoot>
      </table>
      <button onClick={() => handleCheckboxSelection(selectedFlatRows)}>
        Save
      </button>
    </>
  );
}

TABLE IMPLEMENTATION

const MyDataTable = ({
  data
}) => {

const handleCheckboxSelection = (array) => {
    console.log(array.map((d) => d.original));
  };

  const columns = React.useMemo(
    () => [
      {
        Header: "Source ID",
        accessor: "sourceId"
      },
      {
        Header: "Source Name",
        accessor: "sourceName"
      },
      {
        Header: "Flow Rate (GPM)",
        accessor: (d) => {
          return d.flowRate ? numberWithCommas(d.flowRate) : "";
        }
      }
    ],
    []
  );
  return (
    <ReactTable
      columns={columns}
      data={data}
      handleCheckboxSelection={handleCheckboxSelection}
    />
  );
};

Upvotes: 0

Views: 7364

Answers (2)

toki
toki

Reputation: 1004

The props you added to IndeterminateCheckbox are being overwritten. row.getToggleRowSelectedProps() returns an object:

{
   onChange: function,
   checked: Boolean,
   title: String,
   indeterminate: Boolean,
   style: Object
}

which overwrites your properties.

The correct way to do what you want to do would be to use initialState.selectedRowIds property from the useRowSelect API.

Map your data to their included values, then add that array to the initialState as selectedRowIds. In ReactTable.js:

const selectedRowIds = data.map((d, ind) => d.included)
const { 
  // etc 
} = useTable(
  {
    columns,
    data,
    initialState: {selectedRowIds}
  },
  //etc
  ...columns
  }
);

Upvotes: 1

Achraf Drissi
Achraf Drissi

Reputation: 3

you have to refresh your Table.
you can use useState.
example : you can add onClick={this.mychange} to your save Button.

mychange = async () => {
  
    this.setState({
        List: //the new List Data
    })
    
  }

and dont forget the Constructor.

constructor() {
    super();
    this.state = {
      List: anyList,
    };
  }

Upvotes: 0

Related Questions