Search code examples
reactjsmaterial-table

Material-Table with Select (options) fields clears field value on edit mode


I'm using Material-Table with option fields and dropdown component like this:

                  {
                    title: content[lang].Basic_Service_Code,
                    field: "Basic_Service_Code",
                    editable: "always",
                    editComponent: (props) => (
                      <div style={{width:'150px'}}>
                      <Select
                        name="basicservicecode"
                        options={servicesOption}
                        value={props.value}
                        onChange={value => props.onChange(value)}
                        placeholder=""
                        onKeyDown={e => this.handleKey(e)}
                      />
                      </div>
                    ),
                  },

Here is servicesOption:

    const servicesOption = servicesFiltered.map((code) => {
      return { label: code.code, value: code.code };
    });

It works great on Insert (addRow), but when user edits a row, the value of the Select field disappears. It does not show the value. It actually clears the value because it sends "" (empty value) to the server.

Any help would be appreciated.


Solution

  • I assume that your Select component is from React-Select library. If so, try the following to make it work:

    editComponent: ({ value, onChange }) => (
            <Select
              options={fruitsList}
              name="fruitSelect"
              onChange={(selectedOption) => onChange(selectedOption.value)}
              value={value ? value.value : value}
            />
          )
    

    The cause of this behaviour is related to how react-select works, the values are actually objects with value and label properties. Here is a sandbox with a working example, try it out and let me know if that worked for you!

    Full code:

    import React, { Fragment, useState } from "react";
    import MaterialTable from "material-table";
    import Select from "react-select";
    
    const originalData = [
      {
        id: "client 1",
        name: "Anna",
        fruit: "lime"
      }];
    
    export default function CustomEditComponent(props) {
      const fruitsList = [
        { value: "lime", label: "lime-label" },
        { value: "mango", label: "mango-label" }
      ];
    
      const [data, setData] = useState(originalData);
    
      const tableColumns = [
        { title: "Client", field: "id" },
        { title: "Name", field: "name" },
        {
          title: "Choose a Fruit",
          field: "fruit",
          editComponent: ({ value, onChange }) => (
            <Select
              options={fruitsList}
              name="fruitSelect"
              onChange={(selectedOption) => onChange(selectedOption.value)}
              value={value ? value.value : value}
            />
          )
        }
      ];
    
      return (
        <Fragment>
          <MaterialTable
            columns={tableColumns}
            data={data}
            title="Material Table - Editable select component  "
            options={{ search: false, actionsColumnIndex: -1 }}
            editable={{
              onRowAdd: (newData) =>
                new Promise((resolve, reject) => {
                  setTimeout(() => {
                    setData([...data, newData]);
    
                    resolve();
                  }, 1000);
                }),
              onRowUpdate: (newData, oldData) =>
                new Promise((resolve, reject) => {
                  setTimeout(() => {
                    console.log("old:", oldData);
                    console.log("new:", newData);
                    const dataUpdate = [...data];
                    const index = oldData.tableData.id;
                    dataUpdate[index] = newData;
                    setData([...dataUpdate]);
    
                    resolve();
                  }, 1000);
                }),
              onRowDelete: (oldData) =>
                new Promise((resolve, reject) => {
                  setTimeout(() => {
                    const dataDelete = [...data];
                    const index = oldData.tableData.id;
                    dataDelete.splice(index, 1);
                    setData([...dataDelete]);
    
                    resolve();
                  }, 1000);
                })
            }}
          />
        </Fragment>
      );
    }