Material-table: Make row editable on double click

Created on 9 Jun 2020  路  8Comments  路  Source: mbrn/material-table

Hello,
I am trying to make a row editable when double clicked. In my table, I set added an onRowClick prop to detect a double click:

onRowClick={(e, selectedRow) => {
    (e!.target as HTMLElement).ondblclick = () => {
      selectedRow.tableData.editing = "update";
      console.log("force an update here");
    };
  }}

I understand that I might need to force an update to make the row editable, could someone help me with this? I am using a Functional Component, not a class. Thank you.

ask to stackoverflow has a solution question wontfix

All 8 comments

I'm guessing you would have to override the row component in order to do this effectively.

import MaterialTable, { MTableBodyRow } from "material-table";
import React from "react";

const App = () => {
  return (
    <MaterialTable
      title="Default Grouped Field Preview"
      columns={[
        { title: "Name", field: "name" },
        { title: "Surname", field: "surname" },
        { title: "Birth Year", field: "birthYear", type: "numeric" },
        {
          title: "Birth Place",
          field: "birthCity",
          lookup: { 34: "陌stanbul", 63: "艦anl谋urfa" }
        }
      ]}
      data={[
        { name: "Mehmet", surname: "Baran", birthYear: 1987, birthCity: 63 },
        {
          name: "Zerya Bet眉l",
          surname: "Baran",
          birthYear: 2017,
          birthCity: 34
        }
      ]}
      components={{
        Row: props => (
            <MTableBodyRow
              onDoubleClick={() => console.log("double click")}
              {...props}
            />
        )
      }}
    />
  );
};

export default App;

I assume you would also have to design your own editable row.

import MaterialTable, { MTableBodyRow, MTableEditRow } from "material-table";
import React, { useState } from "react";

const App = () => {
  const [rowToEdit, setRowToEdit] = useState(null);

  return (
    <MaterialTable
      title="Default Grouped Field Preview"
      columns={[
        { title: "Name", field: "name" },
        { title: "Surname", field: "surname" },
        { title: "Birth Year", field: "birthYear", type: "numeric" },
        {
          title: "Birth Place",
          field: "birthCity",
          lookup: { 34: "陌stanbul", 63: "艦anl谋urfa" }
        }
      ]}
      editable={{
        isEditable: rowData => rowData.id === rowToEdit,
        onRowUpdate: (newData, oldData) => new Promise((resolve, reject) => {})
      }}
      data={[
        {
          id: 0,
          name: "Mehmet",
          surname: "Baran",
          birthYear: 1987,
          birthCity: 63
        },
        {
          id: 1,
          name: "Zerya Bet眉l",
          surname: "Baran",
          birthYear: 2017,
          birthCity: 34
        }
      ]}
      components={{
        Row: props => {
          const row =
            rowToEdit === props.data.id ? (
              <MTableEditRow {...props} />
            ) : (
              <MTableBodyRow
                onDoubleClick={() => setRowToEdit(props.data.id)}
                {...props}
              />
            );
          return row;
        }
      }}
    />
  );
};

export default App;

This will not render correctly, but maybe it's a point from where you can continue.
codesandbox example

@proohit offers the correct solution - material-table was designed to be malleable, as his solution demonstrates.

Closing this per the correct solution. Let me know if you need me to reopen this issue.

@oze4 Thank you for the start. Unfortunately, I haven't had any luck. Doubling clicking a row opens up the delete row confirmation, and I'm not sure how to fix that.

I get the following warnings in the console:

Warning: React does not recognize the `hasAnyEditingRow` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `hasanyeditingrow` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
Warning: React does not recognize the `treeDataMaxLevel` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `treedatamaxlevel` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

@DDynamic I give MTableEditRow the fault for that as I don't know in detail whats happening in the background.

You can try to write your own "EditableRow" instead of using the one from material-table. I doubt material-table was designed to be used that way.

Replace the component inside the ternary operator with your own editable row. You're in control what's shown and what's not then.

It doesn't matter that the demo shows the onRowDelete after double click, though.

The important thing, and what you should focus on is: the fact that you can handle double clicking a row.

This means you can handle that double click however you please.

There have been a number of issues opened asking about programmatically setting a row to edit state, which have solutions. See here for one example.. Using that logic inside the double click handler should give you what you need.

Please let me know if you still need help and I'll write up a demo.

@oze4 I spent some more time on this, and I was able to get it working inside of a class. Please see below. However, I could use some assistance refactoring this into a functional component. I understand how to use tableRef, but if you could help me replicate the functionality on the this.setState call below, I would be very appreciative.

Row: (props) => (
    <MTableBodyRow
    onDoubleClick={() => {
        this.tableRef.current.dataManager.changeRowEditing(
        props.data,
        "update"
        );
        this.setState({
        ...this.tableRef.current.dataManager.getRenderState(),
        showAddRow: false,
        });
    }}
    {...props}
    />
),

Resolved on Stack Overflow: https://stackoverflow.com/questions/62316709/material-table-make-row-editable-on-click. It would be nice if there was a cleaner way to do this, though.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You can reopen it if it required.

Was this page helpful?
0 / 5 - 0 ratings