I am wondering, is it possible to configure DataProvider/Resource/List to support REST urls like api/users/1/roles
?
For RESTful API it is very common use case to get childs of certain parent entity, but I cant figure it how to setup React Admin and achieve this. I am using custom DataProvider build on OData spec backend.
I understand that I can get roles of certain user by filtered request on api/roles?filter={userId: 1}
or something like that, but my issue is that my users and roles are in many-to-many relation so relation references are stored in pivot table. In other words, I dont have reference on user in roles table so I cant filter them.
Am I overseeing something or is there some approach which I simply dont see?
EDIT: REST API is built in OData spec and it supports many-to-many relations with classic pivot (or intermediate) table. This table is not exposed in API, but is utilized in urls like the one above. So I cant directly access it as a resource.
Schema for User - Role relations looks pretty standard too.
|----------| |-----------| |--------|
| USER | | User_Role | | Role |
|----------| |-----------| |--------|
| Id |-\ | Id | /-| Id |
| Login | \-| UserId | / | Name |
| Password | | RoleId |-/ | Code |
|----------| |-----------| |--------|
TL;DR: By default, React Admin doesn't support nested resource, you have to write a custom data provider.
This question was answered on a past issue: maremelab/react-admin#261
Detailed Answer
The default data provider in React Admin is
ra-data-simple-rest
.As explained on its documentation, this library doesn't support nested resources since it only use the resource name and the resource ID to build a resource URL:
In order to support nested resources, you have to write your own data provider.
Nested resources support is a recurrent feature request but, at the time, the core team don't want to handle this load of work.
I strongly suggest to gather your forces and write an external data provider and publish it like
ra-data-odata
provider. It would be a great addition and we will honored to help you with that external package.Your question was already answer here, but I would like to tell you about my workaround in order for React-Admin work with many-to-many relations.
As said in the mentioned answer you have to extend the DataProvider in order for it to fetch resources of a many-to-many relation. However you need to use the new REST verb, lets suppose
GET_MANY_MANY_REFERENCE
somewhere on your application. Since different REST services/API can have different routes formats to fetch related resources I didn't bother trying to build a new DataProvider, I know is not a great solution, but for short deadlines is considerable simple.My solution was taking inspiration on
<ReferenceManyField>
and build a new component<ReferenceManyManyField>
for many-to-many relations. This component fetches related records oncomponentDidMount
using fetch API. On response uses the response data to build to objects one data being an object with keys being record ids, and values the respective record object, and an ids array with the ids of records. This is passes to children along with other state variables like page, sort, perPage, total, to handle pagination and ordering of data. Be aware that changing the order of the data in a Datagrid means a new request will be made to the API. This component is divided in a controller and a view, like<ReferencemanyField>
, where controller fetches data, manages it and passes it to children and view that receives controller data and passes it to children render its content. That made me possible to render many-to-many relations data on a Datagrid, even if with some limitation, is a component to aggregated to my project and only work with my current API if something changes I would have to change the field to, but as for now it works and can be reused along my app.Implementation details go as follow:
I think the implementation can be improved and be more compatible with React-Admin. In other reference fields data fetch is stored on react-redux state, in this implementation it's not. The relation is not saved anywhere besides the component making application not work on offline since can't fetch data, not even ordering is possible.