简体   繁体   中英

How to select a row in a specific column without triggering the onClick function for that entire row in React Table

I already have my React Table set up that when the user clicks on a row they will be brought to another page, but now I have added a checkbox in the first column that allows the user to have that row highlighted, but when I click the checkbox, it brings the user to another page as it triggers the function called when clicking an entire row.

I have tried to get the column accessor name, and if the column that's clicked is the first one then not to route the user to another page, but I'm having trouble getting information out about what column was selected. I've spent a good bit of time looking at the docs but can't figure it out.

I would really appreciate any help as I am having difficulty getting to grips with React Table in general

RecordTable.js

    import React from "react";
import {
  useTable,
  useFlexLayout,
  useFilters,
  useGlobalFilter,
  useRowSelect
} from "react-table";
import _ from "lodash";
// noinspection ES6CheckImport
import { useHistory } from "react-router-dom";
import Table from "react-bootstrap/Table";

// Define a default UI for filtering
function GlobalFilter({
  preGlobalFilteredRows,
  globalFilter,
  setGlobalFilter
}) {
  return (
    <span>
      <input
        value={globalFilter || ""}
        onChange={e => {
          setGlobalFilter(e.target.value || undefined); // Set undefined to remove the filter entirely
        }}
        placeholder={" Search by any criteria"}
        style={{
          fontSize: "2.0rem",
          width: "100%"
        }}
      />
    </span>
  );
}

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

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

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

export const RecordTable = ({ forms }) => {
  //TODO figure out why react-table crashes if forms is not set to data variable below first
  const data = forms;
  let history = useHistory();

 

  const columns = React.useMemo(
    () => [
      {
        Header: "Disclaimer Form Records",
        columns: [
          {
            Header: "First Name", 
          {
            Header: "Time In",
            accessor: "timeIn"
          },
          {
            Header: "Time Out",
            accessor: "timeOut"
          },
          {
            Header: "€ Price",
            accessor: "totalGroupPrice",
            disableFilters: true,
            disableSortBy: true
          }
        ]
      }
    ],
    []
  );

  const defaultColumn = React.useMemo(
    () => ({
      //minWidth: 20,
      maxWidth: 150,
      width: 120
    }),
    []
  );

  const rowOnClick = (rowObject, column) => {
    console.log("rowObject.original: ", rowObject.original);
    console.log("column.id: ", column);
    history.push("/viewform", { ...rowObject.original });
  };



  // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    state,
    preGlobalFilteredRows,
    setGlobalFilter,
    setHiddenColumns,
  } = useTable(
    {
      columns,
      data,
      defaultColumn
    },
    useFilters,
    useGlobalFilter,
    useFlexLayout,
    useRowSelect,
    hooks => {
      hooks.visibleColumns.push(columns => [
        // Let's make a column for selection
        {
          accessor: "active",
          Header: "Active",
          width: 50,
          maxWidth: 50,
          minWidth: 50,
          Cell: ({ row }) => (
            <div>
              <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
            </div>
          )
        },
        ...columns
      ]);
    }
  );

 

  // Render the UI for your table
  return (
    <div>
      <div>Records: {rows.length}</div>
      <GlobalFilter
        preGlobalFilteredRows={preGlobalFilteredRows}
        globalFilter={state.globalFilter}
        setGlobalFilter={setGlobalFilter}
      />

      <div
        style={{
          height: 500,
          border: "2px solid grey",
          borderRadius: "5px",
          overflow: "scroll"
        }}>
        <Table striped bordered hover responsive={"md"} {...getTableProps()}>
          <thead>
            {headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th {...column.getHeaderProps()}>
                    {column.render("Header")}
                  </th>
                ))}
              </tr>
            ))}
          </thead>

          <tbody {...getTableBodyProps()}>
            {rows.map((row, column, i) => {
              prepareRow(row);
              return (
                <tr
                  {...row.getRowProps({
                    onClick: () => rowOnClick(row, column)
                  })}>
                  {row.cells.map(cell => {
                    return (
                      <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                    );
                  })}
                </tr>
              );
            })}
          </tbody>
        </Table>
      </div>
    </div>
  );
};

You need to set an onClick={e => e.stopPropagation()} on the checkbox.

Technically the click occurred on multiple elements. The checkbox, the cell the row etc.

In JS the event is created on the top element and then propagated ('bubbled') through all DOM elements that are positioned under the mouse cursor. The event bubbles through the different layers and all elements may react on it. But you do want to stop it bubbling in your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM