Context: I wrote an API to handle my user/group/permissions in api-platform, very similar to what we used to have in Symfony 1.4 sfGuardUserPlugin - except that the userGroup association have additional properties:
Exemple of a fake user get request:
{
"@context": "/contexts/User",
"@id": "/users/92",
"@type": "User",
"id": 92,
"firstName": "Joseph",
"lastName": "Chauvet",
"email": "Joseph.Chauvet@fakemail.fr",
"isActive": true,
"userGroups": [
{
"@id": "/user_groups/group=17;user=92",
"@type": "UserGroup",
"group": {
"@id": "/groups/17",
"@type": "Group",
"id": 17,
"name": "adsi",
"role": "ROLE_ADSI"
},
"isManual": false,
"isForbidden": false,
"groupname": "adsi"
}
]
}
sidenote: the groupname property in the userGroup is a virtual property using a getter, not redundant data.
The issue:
I've been trying very hard to get a working UserEdit in react-admin that could handle the Api described above (which is exactly what I wanted, so no issue here).
In order to map the data structure of the users -> userGroups -> groups ressources, I think I need an ArrayInput to iterate the userGroups and a ReferenceInput + selectInput to select the group value.
The list of groups resource in the selectInput is good, but the user's group current value is never shown, so I guess that the issue is with my referenceInput source attribute value.
I've tried many, many, many combinations, using
- getSource()
- adding <FormDataConsumer> Element
- trying to use a direct hook of useGetOne() even if I don't get very well how to the hooks works and that hooks and callback don't play very nicely together.
- even trying to set source "the hard way" like {"userGroups[0].group"} or trying a {"scopedFormData.group"} in the formDataConsumer. but nothing works...
Here's an exemple of one of my (most simple) attempt
export const UserEdit = props => (
<Edit {...props}>
<SimpleForm>
<TextInput source={"firstName"}/>
<TextInput source={"lastName"}/>
<TextInput source={"email"} type="email"/>
<DateInput source={"lastLogin"}/>
<BooleanInput source={"isActive"}/>
<ArrayInput source={"userGroups"}>
<SimpleFormIterator>
<ReferenceInput
source={"group"} //should translate to userGroups[0].group
reference={"groups"}
label={"Groupe"}
>
<SelectInput label={"Groupe"} optionText="name"/>
</ReferenceInput>
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
)
I've alors tried this way:
[...]
<ArrayInput source={"userGroups"}>
<SimpleFormIterator>
<FormDataConsumer>
{({
formData, // The whole form data
scopedFormData, // The data for this item of the ArrayInput
getSource, // A function to get the valid source inside an ArrayInput
...props
}) =>
<ReferenceInput
//source={useGetOne('groups', '/groups/16').data}
source={getSource('group')}
reference={"groups"}
label={"Groupe"}
>
<SelectInput label={"Groupe"} optionText="name"/>
</ReferenceInput>
}
</FormDataConsumer>
</SimpleFormIterator>
I've also tried the useGetOne hook with to fetch data with a direct reference, but the hooks is forbidden in the callback, and I don't understand much of premises in jsx context.
Useless self context: I'm a senior developper new to the whole react/redux paradigm and I'm used to solve problem myself, but I'm stuck on this and spent something like fifty hours to study documentation, bug, sources to get rid of this. My Api-platform stack and react-admin are up-to-date (yes even react-admin today release 3.2.4 that fix an arrayInput bug)
My uneducated wilds guess is that:
- I'm just plainly doing it wrong
- This may be related to the way the HydraProvider parse and store/cache references of related resources instead of passing it to react elements like the simpleRestProvider does.
It may be related, neither me nor my other teammates succeeded to use source={"reference.property"} in any input/field in react-admin using the Hydra dataProvider.
Any help is very very appreciated, one of my teammate added: "Kévin (ie: Dunglas), viens mettre des paillettes dans ma vie"