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 / 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);
}),
}}
/>
);
}
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./ponents/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);
}),
}}
/>
);
}
Share
Improve this question
asked Sep 17, 2019 at 19:56
sci_dudesci_dude
2041 gold badge3 silver badges13 bronze badges
4
-
2
The documentation has an example of a custom editable ponent, showing a simple
input
, to which you could add therequired
attribute. – Heretic Monkey Commented Sep 17, 2019 at 20:01 - @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. – sci_dude Commented Sep 17, 2019 at 20:13
-
5
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 aninput
element. it hastype="text"
. To that, you can addrequired
as an attribute (as the link I provided shows). Therequired
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. – Heretic Monkey Commented Sep 18, 2019 at 0:19 - @HereticMonkey I pletely agree about taking examples and going further with them. Thank you for being thorough. – sci_dude Commented Sep 18, 2019 at 13:06
4 Answers
Reset to default 9Material-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./#/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.
@HereticMonkey's ment essentially solves my question.
Making fields required is done through editable ponents as example shown by Heretic Monkey ^^.
Thank you
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);
}),
}}
/>
);
}
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*/ }