Reputation: 1704
I'm using admin-on-rest. What a great framework ! It is working quite well for my flat resources.
I'm retrieving a list of projects /projects
. I've implemented a ProjectEdit View to edit a given project /projects/:id
export const ProjectEdit = props => {
const projectId = props.match.params.id;
return (
<Edit title={<ProjectTitle />} {...props}>
<TabbedForm>
<FormTab label="Project">
<DisabledInput source="id" />
<TextInput source="name" />
</FormTab>
<FormTab label="Companies">
// WHAT Should I put here to edit my companies list ???
</FormTab>
</TabbedForm>
</Edit>
);
};
I'd like to implement a new tab from which I'd be able to add / remove companies from my project.
GET /projects/:id/companies
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 2,
"name": "My Company"
}
]
}
POST /projects/:id/companies
DELETE /projects/:id/companies/:company_id
I've tried to use a ReferenceManyField
but I'm unable to configure it since my API requires a custom GET. My projects don't have any reference to companies. I can't find any example on how to perform it.
Any clues please ? :)
EDIT1: I'm able to display a list of my project's companies using @malisbad answer. But I'm still not able to display it for edition (eg: Using a ReferenceArrayInput + SelectArrayInput)
Upvotes: 3
Views: 3581
Reputation: 1704
I've found a solution to my problem. I'm not really happy with it but it works... I've created a Datagrid to remove the given company from the project. The Button gets as params record, resourceId
.
I've also added a ReferenceInput to let me add one company at a time when the user hit Save
I've used a custom RestClient.js to handle GET_MANY_REFERENCE
call and use the given url to retrieve my project's companies. I've done the same to handle UPDATE
when the user hit save to add a new company.
EditProject.js :
<FormTab label="Entreprises">
<ReferenceManyField label="Entreprises" reference="companies" target={{ resource: "projects", resourceId: projectId, subresource: "companies" }} allowEmpty>
<Datagrid>
<TextField source="id" />
<TextField source="name" />
<RemoveBtn resourceId={projectId} />
</Datagrid>
</ReferenceManyField>
<ReferenceInput label="Company to Add" source="companyToAdd" reference="companies" allowEmpty>
<SelectInput optionText="name" />
</ReferenceInput>
</FormTab>
RemoveBtn.js :
export class RemoveBtn extends React.Component {
handleRemove = () => {
const {record, resourceId } = this.props;
projectsService.removeCompanyFromProject(resourceId, record.id).then(() => window.location.reload());
};
render() {
return <FlatButton label="Retirer" secondary onClick={this.handleRemove} />;
}
}
Hope it helps...
Upvotes: 2
Reputation: 189
You have to use a custom restClient. I had the same problem, so if you haven't already, create it.
Then look at how the data comes through to each method that you want to have subresources for and modify the URL and request that you'll fire off from there.
For example, in GET_MANY_REFERENCE
I have target
contain an ENUM that specifies that I'm looking for a subresource.
let url = `${apiUrl}/${resource}`;
case GET_MANY_REFERENCE: {
let target;
try {
target = JSON.parse(params.target);
} catch (err) {
target = {};
}
/*
Reference fields do not support the format of
/<resource>/<resource id>/<subresource> so the target parameter is used
to instead indicate the subresource call. See
https://marmelab.com/admin-on-rest/Fields.html#referencefield
for details on reference fields
*/
if (target && target[ENUMS.SUBRESOURCE_IDENTIFIER]) {
/*
If a resource ID is present, it's because the base resource doesn't match the
host resource and needs to use its own ID, not the host resource ID.
*/
if (target[ENUMS.RESOURCE_ID]) {
url = `${url}/${target[ENUMS.RESOURCE_ID]}/${target.subresource}`;
} else {
url = `${url}/${params.id}/${target.subresource}`;
}
}
You can then extend this to other parts of your REST client
Upvotes: 3