Value is not updating in MaterialTable - reactjs

I try to edit the value and update the same but its not updating in MaterialTable
Below is the link which am refering
https://material-table.com/#/docs/features/editable
under this am refering Cell Editable Example
what am missing here
any suggestion?
please refer below snippet
import React from "react";
import MaterialTable from "material-table";
export default function CellEditable() {
const { useState } = React;
const [columns, setColumns] = useState([
{ title: "Name", field: "name" },
{
title: "Surname",
field: "surname",
initialEditValue: "initial edit value"
},
{ title: "Birth Year", field: "birthYear", type: "numeric" },
{
title: "Birth Place",
field: "birthCity",
lookup: { 34: "İstanbul", 63: "Şanlıurfa" }
}
]);
const [data, setData] = useState([
{ name: "Mehmet", surname: "Baran", birthYear: 1987, birthCity: 63 },
{ name: "Zerya Betül", surname: "Baran", birthYear: 2017, birthCity: 34 }
]);
return (
<MaterialTable
title="Cell Editable Preview"
columns={columns}
data={data}
cellEditable={{
onCellEditApproved: (newValue, oldValue, rowData, columnDef) => {
return new Promise((resolve, reject) => {
console.log("newValue: " + newValue);
setTimeout(resolve, 1000);
});
}
}}
/>
);
}

The code you are using never sets the state, it just logs to the console.
You need to set the state at some point. I was able to get this working, though I am uncertain if this is the correct approach.
Update
If you wish to disable a specific column you can add editable: 'never' to the specific column. See below where I added this to the birthYear.
function CellEditable() {
const { useState } = React;
const [columns, setColumns] = useState([
{ title: 'Name', field: 'name' },
{ title: 'Surname', field: 'surname', initialEditValue: 'initial edit value' },
{ title: 'Birth Year', field: 'birthYear', type: 'numeric', editable: 'never' },
{
title: 'Birth Place',
field: 'birthCity',
lookup: { 34: 'İstanbul', 63: 'Şanlıurfa' },
},
]);
const [data, setData] = useState([
{ name: 'Mehmet', surname: 'Baran', birthYear: 1987, birthCity: 63 },
{ name: 'Zerya Betül', surname: 'Baran', birthYear: 2017, birthCity: 34 },
]);
return (
<MaterialTable
title="Cell Editable Preview"
columns={columns}
data={data}
cellEditable={{
onCellEditApproved: (newValue, oldValue, rowData, columnDef) => {
return new Promise((resolve, reject) => {
const clonedData = [ ...data ]
clonedData[rowData.tableData.id][columnDef.field] = newValue
setData(clonedData)
setTimeout(resolve, 1000);
});
}
}}
/>
)
}

Related

How can i use react-drag-listview with functional components to make draggable columns with antd-table?

I'm trying to create a draggable table with antd, but i always use functionalcomponents in react and all the examples and doc that i found in internet is using class components and that=this stufs like. I don't know how can i use react-drag-listview library with the functional components.
this.state = {
columns: [
{
title: <span className="dragHandler">Key</span>,
dataIndex: "key",
render: (text) => <span>{text}</span>,
width: 50
},
{
title: <span className="dragHandler">Name</span>,
dataIndex: "name",
width: 200
},
{
title: <span className="dragHandler">Gender</span>,
dataIndex: "gender",
width: 100
},
{
title: <span className="dragHandler">Age</span>,
dataIndex: "age",
width: 100
},
{
title: <span className="dragHandler">Address</span>,
dataIndex: "address"
}
]
};
const that = this;
this.dragProps = {
onDragEnd(fromIndex, toIndex) {
const columns = [...that.state.columns];
const item = columns.splice(fromIndex, 1)[0];
columns.splice(toIndex, 0, item);
that.setState({
columns
});
},
nodeSelector: "th",
handleSelector: ".dragHandler",
ignoreSelector: "react-resizable-handle"
};
}
This a small piece of code that I'm trying to copy from, but i don't understand it.
Even an exaple of any small code where i can see how to use with functional components it may work for me.
Tis is the url of the example above: https://codesandbox.io/s/table-column-sortable-resizable-st9bt?file=/index.js
React Drag List View Using Functional Component
import "./index.css";
import { useState } from "react";
import { Resizable } from "react-resizable";
import { Table } from "antd";
import ReactDragListView from "react-drag-listview";
const ResizableTitle = (props) => {
const { onResize, width, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className='react-resizable-handle'
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th {...restProps} />
</Resizable>
);
};
const data = [
{ key: "1", name: "Boran", gender: "male", age: "12", address: "New York" },
{ key: "2", name: "JayChou", gender: "male", age: "38", address: "TaiWan" },
{ key: "3", name: "Lee", gender: "female", age: "22", address: "BeiJing" },
{ key: "4", name: "ChouTan", gender: "male", age: "31", address: "HangZhou" },
{ key: "5", name: "AiTing", gender: "female", age: "22", address: "Xi’An" },
];
const components = { header: { cell: ResizableTitle } };
const App = () => {
const [columns, setColumns] = useState([
{
title: <span className='dragHandler'>Key</span>,
dataIndex: "key",
render: (text) => <span>{text}</span>,
width: 50,
},
{
title: <span className='dragHandler'>Name</span>,
dataIndex: "name",
width: 200,
},
{
title: <span className='dragHandler'>Gender</span>,
dataIndex: "gender",
width: 100,
},
{
title: <span className='dragHandler'>Age</span>,
dataIndex: "age",
width: 100,
},
{
title: <span className='dragHandler'>Address</span>,
dataIndex: "address",
},
]);
const onDragEnd = (fromIndex, toIndex) => {
setColumns((prev) => {
const nextColumns = [...prev];
const item = nextColumns.splice(fromIndex, 1)[0];
nextColumns.splice(toIndex, 0, item);
return nextColumns;
});
};
const handleResize = (size, index) => {
setColumns((prev) => {
const nextColumns = [...prev];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
};
const tableColumns = columns.map((col, index) => ({
...col,
onHeaderCell: (column) => ({
width: column.width,
onResize: (e, { size }) => handleResize(size, index),
}),
}));
return (
<ReactDragListView.DragColumn
onDragEnd={onDragEnd}
nodeSelector='th'
handleSelector='.dragHandler'
ignoreSelector='react-resizable-handle'
>
<Table bordered columns={tableColumns} dataSource={data} components={components} />
</ReactDragListView.DragColumn>
);
};
export default App;

Material table onBulkUpdate click don't change icons

I'm using "material-table": "^2.0.3" version. I want to editable all my data and I used onBulkUpdate option in material table document. but after I click the icon next to the search form change to editable but icon doesn't change at all and to give me submit or reject actions to call any function and save my changes.
here is my code:
const [columns, setColumns] = useState([
{ title: 'Name', field: 'name' },
{
title: 'Surname',
field: 'surname',
},
{ title: 'Birth Year', field: 'birthYear' },
{
title: 'Birth Place',
field: 'birthCity',
lookup: { 34: 'İstanbul', 63: 'Şanlıurfa' },
},
]);
const [data, setData] = useState([
{ name: 'Mehmet', surname: 'Baran', birthYear: 1987, birthCity: 63 },
{ name: 'Zerya Betül', surname: 'Baran', birthYear: 2017, birthCity: 34 },
]);
return (
<div className={styles.container}>
<MaterialTable
title='Bulk Edit Preview'
columns={columns}
data={data}
editable={{
onBulkUpdate: (changes) =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000);
}),
}}
/>
</div>
);
I solved my problem by change my package version.
in package.json
"#material-ui/core": "^4.11.4",
"#material-ui/icons": "^4.11.2",
"material-table": "^1.69.3"

material-table: how to edit, add and delete multiple rows in one bulk action?

According to material-table's docs, multiple rows can be edited in bulk and then saved or cancelled to apply or revert the changes. How to also include add and delete actions during bulk editing as well, so that in one bulk action multiple rows can be edited, created or deleted?
What I've tried so far, I can only add and delete one row at a time:
const initialData = [
{
name: "Alberta",
surname: "Abbott",
birthYear: 1984,
birthCity: 63,
},
{
name: "Laura",
surname: "Reynolds",
birthYear: 1988,
birthCity: 34,
},
{
name: "Susie",
surname: "Hayes",
birthYear: 1993,
birthCity: 34,
},
];
const Table = () => {
const [data, setData] = useState(initialData);
const handleBulkUpdate = async (changes) => {
setData((data) => {
const newData = [...data];
Object.entries(changes).forEach(([pos, change]) =>
newData.splice(parseInt(pos), 1, change.newData)
);
return newData;
});
};
const handleAdd = async (newData) => {
setData((data) => [...data, newData]);
};
const handleDelete = async (deletedData) => {
setData((data) => {
const newData = [...data];
newData.splice(deletedData.tableData.id, 1);
return newData;
});
};
return (
<MaterialTable
columns={[
{ title: "Name", field: "name" },
{ title: "Surname", field: "surname" },
{ title: "Birth Year", field: "birthYear", type: "numeric" },
{
title: "Birth City",
field: "birthCity",
lookup: { 34: "İstanbul", 63: "Şanlıurfa" },
},
]}
data={data}
editable={{
onBulkUpdate: handleBulkUpdate,
onRowAdd: handleAdd,
onRowDelete: handleDelete,
}}
/>
);
};

How to add button to material ui table at the bottom?

This is the code for the material ui in react typescript. I am trying to add a button at the bottom which when clicked leads to a form, but after trying many things, I still dont know how to do that?
I just need a simple button at the bottom, any help is appreciated
This is the code from the website
import React from 'react';
import MaterialTable, { Column } from 'material-table';
interface Row {
name: string;
surname: string;
birthYear: number;
birthCity: number;
}
interface TableState {
columns: Array<Column<Row>>;
data: Row[];
}
export default function MaterialTableDemo() {
const [state, setState] = React.useState<TableState>({
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();
setState((prevState) => {
const data = [...prevState.data];
data.push(newData);
return { ...prevState, data };
});
}, 600);
}),
onRowUpdate: (newData, oldData) =>
new Promise((resolve) => {
setTimeout(() => {
resolve();
if (oldData) {
setState((prevState) => {
const data = [...prevState.data];
data[data.indexOf(oldData)] = newData;
return { ...prevState, data };
});
}
}, 600);
}),
onRowDelete: (oldData) =>
new Promise((resolve) => {
setTimeout(() => {
resolve();
setState((prevState) => {
const data = [...prevState.data];
data.splice(data.indexOf(oldData), 1);
return { ...prevState, data };
});
}, 600);
}),
}}
/>
);
}
This is what i want the button to look like:
You can have a component that returns both your MaterialTableDemo and the button.
You can wrap both of them in a div, or use the React.Fragment to inline them.
function TableWithButton() {
return (
<>
<MaterialTableDemo />
<div style={{ width: '100%', textAlign: 'center'}}>
<Button onClick={navigateToForm}>Button</Button>
</div>
</>
);
}
Here is an example

ReactJs MaterialUi onRowUpdate field validation

I have a MaterialTable and I want to validate the fields when editing a line.
For example the following code:
https://codesandbox.io/s/broken-snow-i4jbi?fontsize=14&hidenavigation=1&theme=dark
I have the function setNameError
const [nameError, setNameError] = useState({
error: false,
label: '',
helperText: '',
});
Then the onRowUpdate:
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
if(newData.name === '') {
setNameError({
error: true,
label: 'required',
helperText: 'Required helper text'
});
reject();
return;
}
resolve();
...
}, 600);
})
I want to validate if the field name is empty, if it is empty I want to have this aspect:
validation in the field after click Save button
I can't show the error label, it looks like the setNameError inside the Promise is not working and I don't understand how can I do this.
Found the problem
I was storing the columns in state
const [state, setState] = React.useState({
columns: [
{ title: 'Name', field: 'name',
editComponent: props => (
<TextField
type="text"
required={true}
error = {nameError.error}
label = {nameError.label}
helperText = {nameError.helperText}
value={props.value ? props.value : '' }
onChange={e => 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' },
},
],
data: [
{ name: 'Mehmet', surname: 'Baran', birthYear: 1987, birthCity: 63 },
{
name: 'Zerya Betül',
surname: 'Baran',
birthYear: 2017,
birthCity: 34,
},
],
});
And then passing the state.columns to the MaterialTable component:
<MaterialTable
title="Editable Example"
columns={state.columns}
data={state.data}
...
The solution was to put the columns definition in the MaterialTable component:
return (
<MaterialTable
title="Editable Example"
columns= {[
{ title: 'Name', field: 'name',
editComponent: props => (
<TextField
type="text"
required={true}
error = {nameError.error}
label = {nameError.label}
helperText = {nameError.helperText}
value={props.value ? props.value : '' }
onChange={e => 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' },
},
]}
data={state.data}
...

Resources