Search code examples
reactjsmaterial-uirendertargetmaterial-table

Marerial Table select menu is connected to each row?


My Material-Table has a select menu as one of the columns, however when i select one of the options it changes it for all the rows. How can I make the change row specific so that they are not connected to each other? I realize that the event.target.value approach is applied to all of the mapped select menues, I cant figure out how to make it specific to one.

The row in question is the Facility column

const selectData = ["One", "Two", "Three"];
function Table() {
  const columns = [
    {
      title: "Avatar",
      render: (rowData) => (
        <Avatar
          maxInitials={1}
          size={40}
          round={true}
          name={rowData === undefined ? " " : rowData.first_name}
        />
      ),
    },
    { title: "ID", field: "_id", hidden: true },
    { title: "Name", field: "name" },
    { title: "Email", field: "email" },
    { title: "Company", field: "companyID" },
    { title: "Role", field: "role" },
    {
      title: "Facility",
      render: (rowData) => (
        <FormControl>
          <InputLabel id="demo-mutiple-checkbox-label">Tags</InputLabel>
          <Select
            labelId="demo-mutiple-checkbox-label"
            id="demo-mutiple-checkbox"
            multiple
            value={items}
            onChange={handleChange}
            input={<Input />}
            renderValue={(selected) => selected.join(", ")}
            MenuProps={MenuProps}
          >
            {selectData.map((item) => (
              <MenuItem key={item} value={item}>
                <Checkbox checked={items.indexOf(item) > -1} />
                <ListItemText primary={item} />
              </MenuItem>
            ))}
          </Select>
        </FormControl>
      ),
    },
    { title: "Password", field: "password" },
  ];
  const [data, setData] = useState([]);

  const [items, setItems] = useState([]); //table data

  const handleChange = (event) => {
    setItems(event.target.value);
  };




return (
    <div>
      <MaterialTable
        title="Users"
        columns={columns}
        data={data}
        icons={tableIcons}
        editable={{
          onRowUpdate: (newData, oldData) =>
            new Promise((resolve) => {
              handleRowUpdate(newData, oldData, resolve);
            }),
          onRowAdd: (newData) =>
            new Promise((resolve) => {
              handleRowAdd(newData, resolve);
            }),
          onRowDelete: (oldData) =>
            new Promise((resolve) => {
              handleRowDelete(oldData, resolve);
            }),
        }}
      />
    </div>
  );
}

Image of Table


Solution

  • I think you should define an editComponent in the Facility column, by doing so you will able to modify the value of the current rowData and not just the items variable which is being set as valuein the select component and therefore shown in every row.

    Here is an example:

     const tableColumns = [
        { title: "Client", field: "id" },
        { title: "Name", field: "name" },
    
        {
          title: "Choose a Fruit",
          field: "fruit",
          editComponent: ({ value, onChange }) => (
            <select onChange={(e) => onChange(e.target.value)}>
              <option selected value={value}>
                {value}
              </option>
              {fruitsList.map(
                (item) =>
                  item !== value && (
                    <option key={item} value={item}>
                      {item}
                    </option>
                  )
              )}
            </select>
          )
        }
      ];
    

    Hope that works for you! Full code and sandbox here.