I have a DataGrid anche inside it I have a child array. It's defined like:
{
id: 2,
attachments: [
{attachmentId: 1001, mandatory: true, name: "ordine"},
{attachmentId: 1002, mandatory: true, name: "ordine 2"} ]
..and so on with other fields..
}
Now I want to edit it in mode="form" and I'm not understanding how can I define a editCellComponent to allow the user to add, remove or edit for attachments.
I'm trying to create a Component to manage it with no luck.
interface Props {
data: any
}
export const AttachmentDataGrid : React.FC<Props> = ({ data } : Props) => {
const [ attachments, setAttachments ] = useState<any[]>([]);
useEffect(() => {
setAttachments(data.value);
}, []);
const onValueChanged = (e : any) => {
data.setValue(e.value);
}
const onSelectionChanged = () => {
data.component.updateDimensions();
}
return <>
<GroupItem caption="Attachment"
name="phones-container">
{ attachments.map((att, index) => {
return <GroupItem
name="attachments">
<Label text={`Attachments ${index + 1}`} />
{att.name}
<SimpleItem dataField={`attachments[${index}].name`} />
<SimpleItem dataField={`attachments[${index}].mandatory`} />
</GroupItem>
})}
<SimpleItem itemType="button"
cssClass="add-attachment-button"
onClick={() => { console.log('add-attachment') }}>
>
</SimpleItem>
</GroupItem>
</>
}
This component show me nothing T_T Did someone achieve something like this and can share code to let me understand how to control it?
You can handle a React Component inside the editCellComponent
template, where the callback provided by the devexpress component allows you to handle a nested state and to notify the DataGrid that a row state change is requested.
In case the user will confirm the Form Changes, the changes of the underlying component will be saved, you can check this Sandbox for an example: https://codesandbox.io/s/row-editing-and-editing-events-devextreme-data-grid-forked-my6phn?file=/App.js:2470-3127
Summarizing, the relevant part is the column:
<Column
dataField="Attachments"
width={250}
cellRender={(v) => (
<span>
{v.value
?.map(
(i) =>
`${i.name} - ${
i.mandatory ? "mandatory" : "not mandatory"
}`
)
.join("; ")}
</span>
)}
editCellComponent={({ data }) => {
const { value, setValue } = data;
return (
<AttachmentsGridEditor value={value} setValue={setValue} />
);
}}
/>
And the component itself (please consider these as pure examples, not ready for production usage):
import { useCallback, useEffect, useState } from "react";
export default function AttachmentsGridEditor({ value, setValue }) {
const [localState, setLocalState] = useState(value);
const triggerSampleCheckboxChange = useCallback(
(idx) => {
const vCopy = [...localState];
vCopy[idx] = {
...vCopy[idx],
mandatory: !vCopy[idx].mandatory
};
setLocalState([...vCopy]);
},
[localState, setLocalState]
);
// Because DevExpress does not trigger component re-render, a local state
// has to be kept to allow sync between the two states.
useEffect(() => {
setValue([...localState]);
}, [localState, setValue]);
// TODO: normalize components, compute a better key
return (
<div>
{localState.map((attachment, attachmentIndex) => (
<div key={"attachment" + attachmentIndex + Math.random()}>
<input type="text" readOnly defaultValue={attachment.name} />
<input
type="checkbox"
defaultChecked={attachment.mandatory}
onChange={() => triggerSampleCheckboxChange(attachmentIndex)}
/>
</div>
))}
</div>
);
}