Please refer to the sandbox link here
I'm using my own dynamically generated data and hence using the following in my code:
const onRowEditComplete1 = (e) => {
let _dynamicData = [...dynamicData];
let { newData, index } = e;
_dynamicData[index] = newData;
setDynamicData(_dynamicData); };
And
<DataTable
//value={products2}
value={data}
editMode="row"
dataKey="id"
onRowEditComplete={onRowEditComplete1}
responsiveLayout="scroll">
If I try to change the status from In stock
to Low stock
, It keeps on throwing TypeError dynamicData is not iterable
as you can see in the sandbox above.
However, when I change it to the following to use the data from the primereact sandbox example:
const onRowEditComplete1 = (e) => {
let _products2 = [...products2]; let { newData, index } = e;
_products2[index] = newData;
setProducts2(_products2);
};
<DataTable
value={products2}
editMode="row"
dataKey="id"
onRowEditComplete={onRowEditComplete1}
responsiveLayout="scroll"
>
It doesn't throw any error after editing a row and saving the changes. How to fix the error in case of the data that I'm using there so that it starts saving properly?
My complete code if needed for reference:
export const FileUploadDemo = () => {
const [totalSize, setTotalSize] = useState(0);
const toast = useRef(null);
const fileUploadRef = useRef(null);
//start:Row Editing Work
const [products2, setProducts2] = useState(null);
const [dynamicData, setDynamicData] = useState(null);
const statuses = [
{ label: "In Stock", value: "INSTOCK" },
{ label: "Low Stock", value: "LOWSTOCK" },
{ label: "Out of Stock", value: "OUTOFSTOCK" }
];
const dataTableFuncMap = {
products2: setProducts2
//dynamicData: setDynamicData
};
const productService = new ProductService();
useEffect(() => {
fetchProductData("products2");
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const fetchProductData = (productStateKey) => {
productService
.getProductsSmall()
.then((data) => dataTableFuncMap[`${productStateKey}`](data));
};
const getStatusLabel = (status) => {
switch (status) {
case "INSTOCK":
return "In Stock";
case "LOWSTOCK":
return "Low Stock";
case "OUTOFSTOCK":
return "Out of Stock";
default:
return "NA";
}
};
// const onRowEditComplete1 = (e) => {
// // console.log("Testing e");
// // console.log(e);
// let _products2 = [...products2];
// let { newData, index } = e;
// _products2[index] = newData;
// setProducts2(_products2);
// };
const onRowEditComplete1 = (e) => {
console.log("Testing e")
console.log(e);
let _dynamicData = [...dynamicData];
let { newData, index } = e;
_dynamicData[index] = newData;
setDynamicData(_dynamicData);
};
const textEditor = (options) => {
return (
<InputText
type="text"
value={options.value}
onChange={(e) => options.editorCallback(e.target.value)}
/>
);
};
const statusEditor = (options) => {
return (
<Dropdown
value={options.value}
options={statuses}
optionLabel="label"
optionValue="value"
onChange={(e) => options.editorCallback(e.value)}
placeholder="Select a Status"
itemTemplate={(option) => {
return (
<span
className={`product-badge status-${option.value.toLowerCase()}`}
>
{option.label}
</span>
);
}}
/>
);
};
const priceEditor = (options) => {
return (
<InputNumber
value={options.value}
onValueChange={(e) => options.editorCallback(e.value)}
mode="currency"
currency="USD"
locale="en-US"
/>
);
};
const statusBodyTemplate = (rowData) => {
return getStatusLabel(rowData.inventoryStatus);
};
const priceBodyTemplate = (rowData) => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
}).format(rowData.price);
};
//END:Row Editing Work
const onUpload = (e) => {
toast.current.show({
severity: "info",
summary: "Success",
detail: "File Uploaded"
});
console.log("File Upload event e");
console.log(e);
setTotalSize(e.length);
};
let data = [];
for (let i = 0; i < 4; i++) {
data[i] = {
id: i + 1,
code: "cm230f032" + i + 1,
name: "Gaming Set" + i + 1,
description: "Product Description" + i + 1,
image: "gaming-set.jpg" + i + 1,
price: i + 2,
category: "Electronics" + i + 1,
quantity: i + 3,
inventoryStatus: "INSTOCK",
rating: i + 1
};
}
console.log("Printing Data");
console.log(data)
// var result = Object.keys(data).map((key) => [Number(key), data[key]]);
// console.log(result);
return (
<div>
<Toast ref={toast}></Toast>
<Tooltip target=".custom-choose-btn" content="Choose" position="bottom" />
<Tooltip target=".custom-upload-btn" content="Upload" position="bottom" />
<Tooltip target=".custom-cancel-btn" content="Clear" position="bottom" />
<div className="card">
<h5>Advanced</h5>
<FileUpload
name="demo[]"
url="https://primefaces.org/primereact/showcase/upload.php"
//onUpload={onUpload}
customUpload
uploadHandler={onUpload}
multiple
accept="image/*"
maxFileSize={1000000}
emptyTemplate={
<p className="m-0">Drag and drop files to here to upload.</p>
}
/>
</div>
<div className="datatable-editing-demo">
<Toast ref={toast} />
<div className="card p-fluid">
<h5>Row Editing</h5>
<DataTable
//value={products2}
value={data}
editMode="row"
dataKey="id"
onRowEditComplete={onRowEditComplete1}
responsiveLayout="scroll"
>
<Column
field="code"
header="Code"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="name"
header="Name"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="inventoryStatus"
header="Status"
body={statusBodyTemplate}
editor={(options) => statusEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="price"
header="Price"
body={priceBodyTemplate}
editor={(options) => priceEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
rowEditor
headerStyle={{ width: "10%", minWidth: "8rem" }}
bodyStyle={{ textAlign: "center" }}
></Column>
</DataTable>
</div>
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadDemo />, rootElement);