Incorporate a personalized add-button into the material-table interface

My current setup includes a basic material-table structured like this:

<MaterialTable
    options={myOptions}
    title="MyTitle"
    columns={state.columns}
    data={state.data}
    tableRef={tableRef} // Not functioning properly
    editable={{
      onRowAdd: ...,
      onRowDelete: ...,
      onRowUpdate: ...
    }}
  />;

I am interested in adding a new custom add button (without editing the existing one): each row in the Bar Column should have its own unique add button. I've checked through the MaterialTable source code, but I'm having trouble replicating the code used for the default add button, which looks like this:

        calculatedProps.actions.push({
          icon: calculatedProps.icons.Add,
          tooltip: localization.addTooltip,
          position: "toolbar",
          disabled: !!this.dataManager.lastEditingRow,
          onClick: () => {
            this.dataManager.changeRowEditing();
            this.setState({
              ...this.dataManager.getRenderState(),
              showAddRow: !this.state.showAddRow,
            });
          },
        });

I specifically can't seem to access the dataManager variable.

https://i.stack.imgur.com/9wEzH.png

This is how the current table appears, and I'm aiming to incorporate the add button where indicated by the red marker.

Answer №1

Here is the solution you've been searching for:

https://i.stack.imgur.com/gFIj9.gif

The Actions column displays the default actions set. I included a specific button using custom column rendering (documentation):

//..previous columns definition
{
  title: "Custom Add",
  field: "internal_action",
  editable: false,
  render: (rowData) =>
    rowData && (
      <IconButton
        color="secondary"
        onClick={() => addActionRef.current.click()}
      >
        <AddIcon />
      </IconButton>
    )
}

*Using rowData as conditional prevents rendering while filling the addition row.

Next, I triggered the add action following the steps outlined here:

const MyComponent() {

const addActionRef = React.useRef();

return (
    <>
        <button onClick={() => addActionRef.current.click()}>
            Add new item
        </button>

        <MaterialTable
            //...
            components={{
                Action: props => {
                    //If it's not the add action
                    if (typeof props.action === typeof Function || props.action.tooltip !== 'Add') {
                            return <MTableAction {...props} />
                    } else {
                            return <div ref={addActionRef} onClick={props.action.onClick}/>;
                    }}
                }}
            editable={{
                onRowAdd: (newData, oldData) => Promise.resolve(); //your callback here
            }}
        />
    </>
);
}

I expanded the original snippet to complete the addition cycle. If you need to manage different types of actions, check out the Editable section in the official documentation.

Hope this solution fits your needs! You can find the full code and sandbox example here:

import React, { Fragment, useState } from "react";
import MaterialTable, { MTableAction } from "material-table";
import AddIcon from "@material-ui/icons/AddAlarm";
import IconButton from "@material-ui/core/IconButton";

export default function CustomEditComponent(props) {
const tableRef = React.createRef();
const addActionRef = React.useRef();

const tableColumns = [
    { title: "Client", field: "client" },
    { title: "Name", field: "name" },
    { title: "Year", field: "year" },
    {
    title: "Custom Add",
    field: "internal_action",
    editable: false,
    render: (rowData) =>
        rowData && (
        <IconButton
            color="secondary"
            onClick={() => addActionRef.current.click()}
        >
            <AddIcon />
        </IconButton>
        )
    }
];

const [tableData, setTableData] = useState([
    {
    client: "client1",
    name: "Mary",
    year: "2019"
    },
    {
    client: "client2",
    name: "Yang",
    year: "2018"
    },
    {
    client: "client3",
    name: "Kal",
    year: "2019"
    }
]);

return (
    <Fragment>
    <MaterialTable
        tableRef={tableRef}
        columns={tableColumns}
        data={tableData}
        title="Custom Add Mode"
        options={{
        search: false
        }}
        components={{
        Action: (props) => {
            //If isn't the add action
            if (
            typeof props.action === typeof Function ||
            props.action.tooltip !== "Add"
            ) {
            return <MTableAction {...props} />;
            } else {
            return <div ref={addActionRef} onClick={props.action.onClick} />;
            }
        }
        }}
        actions={[
        {
            icon: "save",
            tooltip: "Save User",
            onClick: (event, rowData) => alert("You saved " + rowData.name)
        }
        ]}
        editable={{
        onRowAdd: (newData) =>
            Promise.resolve(setTableData([...tableData, newData]))
        }}
    />
    </Fragment>
);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on displaying a particular JSON attribute?

After starting with a JSON string, attempting to convert it into a JSON object and then trying to print a specific field (such as firstName), I am getting undefined. What could be the issue here? Thank you for your help! var string = '{"firstName ...

Navigating back to the previous page while retaining modifications using AngularJS

When I use the products table to conduct an advanced search, view details of a specific item and then click on the cancel button to return to the list, all my research inputs are reset... Is there a way for me to go back to where I was before? Can I retri ...

Transforming the text color after clicking on it on Squarespace - here's how to do it!

How can I make text change color upon clicking in Squarespace? Where should I place the block id in the code to target a specific block? Check out the code snippet I've been experimenting with: <script> document.getElementById('chang ...

Setting up a connection to MongoDB on a local network using express and mongoose

As I set up a server with express and mongoose, my goal is to make it accessible on other devices within my local network. To achieve this, I configured the bind_ip variable to 0.0.0.0 in the Mongodb configuration file. const connection = mongoose .co ...

The challenges with implementing makeStyles in React Material UI

const useStyles = makeStyles((theme) => ({ toolbarMargin: { ...theme.mixins.toolbar, marginBottom: "3em", }, logo: { height: "7em", }, tabContainer: { marginLeft: "auto", }, tab: { ...theme ...

Material UI makes it possible for the ToggleButtonGroup to maintain a consistent fixed size regardless of its content

Seeking a solution to ensure consistent button sizes, even when they have no content. The desired size is displayed below, functioning properly as long as the top and bottom buttons contain some content: https://i.stack.imgur.com/5zVNM.png When the midd ...

Looking to disable the back button in the browser using next.js?

How can I prevent the browser's back button from working in next.js? // not blocked... Router.onRouteChangeStart = (url) => { return false; }; Does anyone know of a way to disable the browser's back button in next.js? ...

Is it possible to load a JS file without using the require function?

Is there a method to load a JavaScript file without using require, but with fs for instance? I am aware that for JSON files I can utilize: const jsonFile = JSON.parse(fs.readFileSync("/jsonfile.json")) Can the same be done for a JavaScript file? I am inq ...

Error: 403 - Access Denied. This error occurs when the submit form button is clicked

Upon running the nodeJS backend successfully, I encountered an error when submitting form data on the contact page. The error seems to be related to using the SendGrid API key for sending emails. I am perplexed by the specific error that is occurring and ...

Error message: The 'Access-Control-Allow-Origin' policy is preventing access in a react express docker application

I have successfully set up a front-end React application and a Node/Express API using Docker. The React app is currently running on localhost:3000, while the API is running on localhost:9000. Both applications are fully functional. However, I am encounteri ...

Problem with the show/hide feature on jQuery. Automatically scrolls to the beginning of the page

On my website, I have successfully implemented two basic Show / Hide links that are working great. Here is the HTML code: <!DOCTYPE html> <html lang="en"> <head profile="http://gmpg.org/xfn/11"> <meta http-equiv="Content-Type" conte ...

Attempting to create a login and registration form

Hello, I am attempting to create a form that can generate new user accounts and passwords. These values should be stored from the input tag when the user clicks on the register button. Unfortunately, I am encountering an issue where clicking the register ...

Struggling to fetch a custom attribute from the HTML Option element, receiving [object Object] as the result instead

I've been facing a challenging issue all day. My task involves making an ajax call to a predefined JSON file and trying to save certain contents into option tags using custom attributes. However, every time I attempt to retrieve the data stored in the ...

Issues encountered when setting up a Context Provider in React using TypeScript

I am currently in the process of setting up a Cart context in my React TypeScript project, inspired by the implementation found here: https://github.com/AlexSegen/react-shopping-cart/blob/master/src/contexts/CartContext.js. I'm encountering some conf ...

Is it possible to adjust the color and placement of the CircularProgress component?

Utilizing the CircularProgress component provided by Material has been a goal of mine. In my efforts to achieve this, I developed a component with the intention of customizing its color: import React, { Component } from 'react'; import { withSt ...

Generating output from a callback function in TypeScript

When I execute a graphql query, the showUsers function is supposed to display all users (styled as boxes). However, at the moment, nothing is showing up. I am utilizing a functional component instead of a class component. This function is invoked after m ...

Tips for including markdown content within components in MDX files

I'm currently in the process of utilizing MDX pages along with React components for a project. My issue lies in wanting to generate HTML when adding text inside a component, similar to how it works with content outside of components. However, I'v ...

There are multiple sets of radio buttons within nested ng-repeats, but only the final group displays the selected value

I am having an issue with updating a form that contains multiple radio buttons based on data retrieved from an API. The challenge is that only the last set of radio buttons displays the value correctly. Below is the code snippet I am using (angular bracket ...

Error encountered when accessing color background in the state of Material UI

My eyes are feeling strained, and I'm working on implementing a slider that can adjust both the radius and color of a button. This sandbox successfully updates the radius. Here is the code: (Code content) Currently, my focus is on utilizing ...

I am experiencing excessive paper skipping in my printer

I have been using the 80 column dot matrix printer. However, after each printout, the paper skips two times resulting in a lot of wasted paper. How can I resolve this issue? Currently, I am only utilizing the window.print() JavaScript function. Are there ...