使用 admin-on-rest 添加嵌套资源

Add Nested resource using admin-on-rest

我正在使用 admin-on-rest。多么棒的框架!它对我的平面资源非常有效。

我正在检索项目列表 /projects。我已经实现了一个 ProjectEdit 视图来编辑给定的项目 /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>
    );
};

我想实现一个新选项卡,我可以从中添加/删除项目中的公司。

获取/projects/:id/companies

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 2,
            "name": "My Company"
        }
    ]
}

POST /projects/:id/companies

删除/projects/:id/companies/:company_id

我尝试使用 ReferenceManyField,但我无法配置它,因为我的 API 需要自定义 GET。我的项目没有任何公司参考。我找不到任何关于如何执行它的示例。

有什么线索吗? :)


EDIT1: 我可以使用 显示我的项目公司列表。但我仍然无法在版本中显示它(例如:使用 ReferenceArrayInput + SelectArrayInput)

您必须使用自定义 restClient。我遇到了同样的问题,所以如果您还没有,请创建它。

然后查看数据如何到达您希望为其拥有子资源的每个方法并修改 URL 并请求您从那里开始。

例如,在 GET_MANY_REFERENCE 中,我 target 包含一个指定我正在寻找子资源的 ENUM。

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}`;
      }
    }

然后您可以将其扩展到 REST 客户端的其他部分

我找到了解决问题的办法。我对它不是很满意,但它确实有效...我创建了一个 Datagrid 以从项目中删除给定的公司。按钮作为参数 record, resourceId.

我还添加了一个 ReferenceInput,让我在用户点击 Save

时一次添加一家公司

我使用了自定义 RestClient.js 来处理 GET_MANY_REFERENCE 调用并使用给定的 url 来检索我项目的公司。当用户点击保存以添加新公司时,我对 UPDATE 做了同样的处理。

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} />;
    }
}

希望对您有所帮助...