Is it possible to make fields required on material-table
Asked Answered
L

4

5

I am working on a project, where I basically do crud using material-table interface. I am wondering is there a way if I can make fields required if I want too?

I tried researching but not much results. Please see the code below which is straight forward from https://material-ui.com/components/tables/ last example. Of course I have modified on my codebase for my personal use and everything works fine, but I am not sure how is it possible to make fields required if I want too? If yes, how would I do it? Would I pass something as a prop option on MaterialTable ?

Thank you for any suggestions.

import React from 'react';
import MaterialTable from 'material-table';

export default function MaterialTableDemo() {
  const [state, setState] = React.useState({
    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,
      },
    ],
  });

  return (
    <MaterialTable
      title="Editable Example"
      columns={state.columns}
      data={state.data}
      editable={{
        onRowAdd: newData =>
          new Promise(resolve => {
            setTimeout(() => {
              resolve();
              const data = [...state.data];
              data.push(newData);
              setState({ ...state, data });
            }, 600);
          }),
        onRowUpdate: (newData, oldData) =>
          new Promise(resolve => {
            setTimeout(() => {
              resolve();
              const data = [...state.data];
              data[data.indexOf(oldData)] = newData;
              setState({ ...state, data });
            }, 600);
          }),
        onRowDelete: oldData =>
          new Promise(resolve => {
            setTimeout(() => {
              resolve();
              const data = [...state.data];
              data.splice(data.indexOf(oldData), 1);
              setState({ ...state, data });
            }, 600);
          }),
      }}
    />
  );
}
Littlest answered 17/9, 2019 at 19:56 Comment(4)
The documentation has an example of a custom editable component, showing a simple input, to which you could add the required attribute.Drysalt
@HereticMonkey I looked before, and even now, I don't see the example for making inputs/fields required, only for readonly but not making editable, maybe I am missing something. Thank you.Littlest
As I mentioned, use the one for a Custom Edit Component. The last one at the bottom of the screen. You see that? Look at the code. It has a property, editComponent that shows the use of an input element. it has type="text". To that, you can add required as an attribute (as the link I provided shows). The required attribute is not part of the example. I'm telling you to add it your self. This is what programming is all about. Taking examples and going further with them.Drysalt
@HereticMonkey I completely agree about taking examples and going further with them. Thank you for being thorough.Littlest
L
3

@HereticMonkey's comment essentially solves my question.

Making fields required is done through editable components as example shown by Heretic Monkey ^^.

Thank you

Littlest answered 18/9, 2019 at 13:21 Comment(1)
I think we can use formik in the edit so before updating we can do all validation like required and other.Shaikh
S
9

Material-table has native support for validation which can trivially be used to make a field required. All you have to do is specify the validation field in the columns specification as per docs here: https://material-table.com/#/docs/features/validation.

Here's what that would look like for your code, say if you wanted to make the "Surname" required:

...
  const [state, setState] = React.useState({
    columns: [
      { title: 'Name', field: 'name' },
      {
          title: 'Surname',
          field: 'surname',
          validate: rowData => Boolean(rowData.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,
      },
    ],
  });
...

p.s. there's no need to put your columns data in the state here unless it's going to change, which seems unlikely in this case.

Strongminded answered 30/11, 2020 at 10:29 Comment(0)
L
3

@HereticMonkey's comment essentially solves my question.

Making fields required is done through editable components as example shown by Heretic Monkey ^^.

Thank you

Littlest answered 18/9, 2019 at 13:21 Comment(1)
I think we can use formik in the edit so before updating we can do all validation like required and other.Shaikh
E
3

You need to use editComponent,TextField and validation handling on onRowAdd and onRowUpdate.

See below sample revise code.

import React from "react";
import MaterialTable from "material-table";
import TextField from "@material-ui/core/TextField";

export default function App() {

const [nameError, setNameError] = React.useState({
    error: false,
    label: "",
    helperText: "",
    validateInput: false,
});

const columnsHeader = [
    {
        title: "Name",
        field: "name",
        editComponent: (props) => (
            <TextField
                type="text"
                error={
                    !props.value &&
                    nameError.validateInput &&
                    props.rowData.submitted
                        ? nameError.error
                        : false
                }
                helperText={
                    !props.value &&
                    nameError.validateInput &&
                    props.rowData.submitted
                        ? nameError.helperText
                        : ""
                }
                value={props.value ? props.value : ""}
                onChange={(e) => {
                    if (nameError.validateInput) {
                        setNameError({
                            ...nameError,
                            validateInput: false,
                        });
                    }

                    props.onChange(e.target.value);
                }}
            />
        ),
    },
    { title: "Surname", field: "surname" },
    { title: "Birth Year", field: "birthYear", type: "numeric" },
    {
        title: "Birth Place",
        field: "birthCity",
        lookup: { 34: "İstanbul", 63: "Şanlıurfa" },
    },
    { title: "submitted", field: "submitted", hidden: true },
];

const [state, setState] = React.useState({
    data: [
        {
            name: "Mehmet",
            surname: "Baran",
            birthYear: 1987,
            birthCity: 63,
            submitted: false,
        },
        {
            name: "Zerya Betül",
            surname: "Baran",
            birthYear: 2017,
            birthCity: 34,
            submitted: false,
        },
    ],
});

return (
    <MaterialTable
        title="Editable Example"
        columns={columnsHeader}
        data={state.data}
        editable={{
            onRowAdd: (newData) =>
                new Promise((resolve, reject) => {
                    setTimeout(() => {
                        newData.submitted = true;
                        if (!newData.name) {
                            setNameError({
                                error: true,
                                label: "required",
                                helperText: "Name is required.",
                                validateInput: true,
                            });
                            reject();
                            return;
                        }
                        resolve();

                        const data = [...state.data];
                        data.push(newData);
                        setState({ ...state, data });
                    }, 600);
                }),
            onRowUpdate: (newData, oldData) =>
                new Promise((resolve, reject) => {
                    setTimeout(() => {
                        newData.submitted = true;
                        if (!newData.name) {
                            setNameError({
                                error: true,
                                label: "required",
                                helperText: "Name is required.",
                                validateInput: true,
                            });
                            reject();
                            return;
                        }
                        resolve();
                        const data = [...state.data];
                        data[data.indexOf(oldData)] = newData;
                        setState({ ...state, data });
                    }, 600);
                }),
            onRowDelete: (oldData) =>
                new Promise((resolve) => {
                    setTimeout(() => {
                        resolve();
                        const data = [...state.data];
                        data.splice(data.indexOf(oldData), 1);
                        setState({ ...state, data });
                    }, 600);
                }),
        }}
    />
);

}

Eatton answered 27/4, 2020 at 16:1 Comment(0)
C
1

just validate and use Reject() like this ( calling reject() keeps open row editable ):

 onRowAdd: (newData) =>
        new Promise((resolve) => {
          if(---!validate(newData)---) {
            // alert('required');
            reject();
          }else{ /*addRow*/ }
Caudex answered 20/4, 2020 at 6:20 Comment(1)
can you be more specific on your answer? please describe the code better.Cushat

© 2022 - 2024 — McMap. All rights reserved.