问题
I am trying to understand what the right approach would be to address nested endpoints, let's assume I have a many to many books
and authors
relationship, and an API which exposes api/authors
, api/books
, and api/authors/{id}/books
. This is a common design pattern.
The CRUD on api/authors
works beautifully in react-admin. However, under the authors <Show>
I want to show a <Datagrid>
of all the books with pagination and sorting, which my api makes available under api/authors/{id}/books
.
What is the right approach to make a datagrid of such a nested endpoint?
I've looked into the <ReferenceManyField>
which works well in the one to many context but doesn't allow accessing nested endpoints, only filtering an endpoint.
Ideally I would want something that is along the lines of:
<Show {...props}>
<TabbedShowLayout>
<Tab label="Books">
<NestedResourceField reference="books" nestedResource={`authors/${props.record.id}/books`} pagination={<Pagination/>} >
<Datagrid>
<TextField source="name" />
</Datagrid>
</NestedResourceField>
</Tab>
</TabbedShowLayout>
</Show>
Note that <NestedResourceField>
is a hypothetical component which would have a behavior very similar to <ReferenceManyField> but would accept a nested endpoint under nestedResource
instead of target
.
I am struggling to understand what the design strategy should be for the hypothetical <NestedResourceField>
in order to re-use as much of the react-admin framework as possible.
It would be straightforward to "manually" do the fetch myself and list the content but then I would lose all the pagination, filtering, sorting, etc... that comes with react-admin and the fact that books
is an already defined resource.
My question is similar to these unanswered questions:
custom routes in react-admin
custom path for resource route in react-admin
Edit
Turns out an almost identical question which I had not found previously was posted here: Support for resource nesting
回答1:
So I decided to solve this with a hack in the dataProvider.
Keeping with the above example and using the stock ReferenceManyField:
<Show {...props}>
<TabbedShowLayout>
<Tab label="Books">
<ReferenceManyField reference="books" target="_nested_authors_id" pagination={<Pagination/>} >
<Datagrid>
<TextField source="name" />
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
</Show>
I then modified my dataProvider, which is a fork of ra-jsonapi-client.
I changed index.js
under the case GET_MANY_REFERENCE
from this:
// Add the reference id to the filter params.
query[`filter[${params.target}]`] = params.id;
url = `${apiUrl}/${resource}?${stringify(query)}`;
to this:
// Add the reference id to the filter params.
let refResource;
const match = /_nested_(.*)_id/g.exec(params.target);
if (match != null) {
refResource = `${match[1]}/${params.id}/${resource}`;
} else {
query[`filter[${params.target}]`] = params.id;
refResource = resource;
}
url = `${apiUrl}/${refResource}?${stringify(query)}`;
So basically I just remap the parameters to the url for the special case where the target
matches a hard coded regex.
ReferenceManyField
would normally have caused the dataProvider to call api/books?filter[_nested_authors_id]=1
and this modification makes the dataProvider call api/authors/1/books
instead. It is transparent to react-admin.
Not elegant but it works and doesn't seem to break anything on the front end.
来源:https://stackoverflow.com/questions/56907751/datagrid-for-nested-endpoints-in-react-admin