I'm using react-admin with Amplify. One of my graphql types has an AWSJSON field containing an array of statuses for a batchJob. I'd like this array to be shown in a datagrid that the user can expand to see result of each item in the batch.
The data is returned from the API as stringified JSON. How can I JSON.parse the data then pass it to ArrayField to be rendered by Datagrid in my list/show components?
The contents of the field look like this:
[{"reference":"11134","status":"OK"},{"reference":"10278","status":"OK"}]
UPDATE: the answer below was after I updated the data model a bit to:
[{"id": "somerandomuid", "clientReference":"11134","status":"OK"}]
My code looks like this:
Schema:
type JobTask
@model
@auth(
rules: [
{ allow: owner }
{ allow: groups, groups: ["admins"] }
]
) {
id: ID!
results: AWSJSON
status: String
expiryDate: AWSTimestamp! @ttl
}
Show Component:
export const TaskShow = (props) => {
return (
<Show title={props.header} {...props}>
<SimpleShowLayout>
<Datagrid expand={<ResultsPanel />}>
<TextField
key={cuid()}
fullWidth={true}
source="id"
label="Batch Id"
/>
<TextField
key={cuid()}
fullWidth={true}
source="status"
label="Status"
/>
</Datagrid>
</SimpleShowLayout>
</Show>
);
ResultsPanel Component:
const ResultsPanel = (props) => {
console.log(props)
let resultsArray = JSON.parse(JSON.parse(props.record.results));
console.log(resultsArray);
return (
<>
{resultsArray.map((result) => {
return (
<ArrayField>
<Datagrid>
<TextField source="reference" />
<TextField source="status" />
</Datagrid>
</ArrayField>
);
})}
</>
);
};
But all I get is:
Thought I'd post my findings for anyone else who might be struggling with this.
Datagrid requires a context, which a list component will provide for it, but as this is in a show component, I was trying to use Array instead to provide the context.
ArrayField component requires a source prop that must be a string that maps exactly to a field/property in the API response; it can't be an arbitrary object/array. The property the string maps to however must be an array, and there's no way to tell the component to process the contents of that field/property before using it. So Arrayfield is out as a context provider.
As Array doesn't work with my data structure, I thought I could use RA's listcontextprovider, which isn't very well documented, but does seem to allow you to build a context that can be used by datagrid, as far as I can tell. But it always gave me an error when I used it with the correct props (as far as I could tell, anyway - as I say, the documentation is a bit sparse).
In the end, I abandoned native RA components as a bad fit for my use-case and went with writing a custom field component that does what I need instead (i.e. parse the field from the record and pass the array to a datagrid to render). I used native MUI datagrid, which works like a charm:
const ResultsPanel = (props) => {
let resultsArray = JSON.parse(JSON.parse(props.record.results));
let columns = [
{ field: "id", headerName: "Item Id", flex: 1 },
{ field: "clientReference", headerName: "Your Reference", flex: 1 },
{ field: "status", headerName: "Import Status", flex: 1 },
];
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid columns={columns} rows={resultsArray} />
</div>
);
};