如何在admin-on-rest中创建可搜索的添加引用按钮/操作?

问题描述 投票:7回答:1

考虑一个我有一个功能性JSON后端,以及admin-on-rest资源companyusercompany_user的情况。

数据如下

company

  • ID
  • 那么
  • 地址......等

user

  • ID
  • 那么
  • 电话
  • 地址......等

company_user

  • ID
  • company_id(参考公司)
  • user_id(引用用户)
  • 职位......等

company_user资源类型提供单独的顶级资源视图非常容易;但它应该可以根据用户和每个公司进行编辑,最好是在user的选项卡或company资源视图中。

因此出现了问题:如何为user资源创建一个选项卡,我可以在其中列出当前的company-references(company_user行),但在同一个选项卡中,我需要一种理智的方式来执行以下功能:

  1. 搜索此用户当前未提及的所有公司(当然,有一个API调用);
  2. company_user集合中添加一行;
  3. 刷新选项卡
admin-on-rest
1个回答
0
投票

处理这种关系的最简单方法是在模型上提供一个额外的字段,用作关系的表示。

例如,我们需要从用户那里看到他的公司:公开一个新领域user.company_ids。此字段不必位于数据库中,您的API或代理可以在此字段中列出相关的公司ID,对于写入请求,可以使用它来创建,更改或删除关系。

实施此字段后,admin-on-rest非常容易配置。我制作了一个完整的片段:https://codesandbox.io/s/r04y8rn96p

首先,编写您的顶级资源:

<Admin
    authClient={authClient}
    restClient={restClient}
    title="Example Admin"
    locale="en"
    messages={messages}
  >
    <Resource
      name="companies"
      list={CompanyList}
      create={CompanyCreate}
      edit={CompanyEdit}
      show={CompanyShow}
      remove={Delete}
      icon={CompanyIcon}
    />
    <Resource
      name="users"
      list={UserList}
      create={UserCreate}
      edit={UserEdit}
      remove={Delete}
      icon={UserIcon}
      show={UserShow}
    />
    <Resource
      name="company_user"
      icon={CompanyUserIcon}
      list={CompanyUserList}
      create={CompanyUserCreate}
      show={CompanyUserShow}
      remove={Delete}
    />
</Admin>

然后,您可以在额外字段上使用ReferenceArrayInput作为用户模型,就像一对多关系一样。

export const UserEdit = ({ ...props }) => (
  <Edit title={<UserTitle />} {...props}>
    <TabbedForm>
      <FormTab label="User Infos">
        <TextInput source="name" />
        <DateInput source="published_at" defaultValue={() => new Date()} />
        <TextInput source="company_ids" />
      </FormTab>
      <FormTab label="Companies">
        <ReferenceArrayInput source="company_ids" reference="companies">
          <SelectArrayInput optionText="title" />
        </ReferenceArrayInput>
      </FormTab>
    </TabbedForm>
  </Edit>
);

由于想法是将关系模拟为额外的字段,您可以从后端(最佳选择)或通过restClient处理前端。以下是只读关系的虚拟示例:

// It's better to implement these rules on the backend
const improvedRestClient = (type, resource, params) => {
  return restClient(type, resource, params).then((response) => {
    // Inject company_ids into user
    if (type === 'GET_ONE' && resource === 'users') {
      return restClient('GET_LIST', 'company_user', defaultOptions).then(({ data: companyUsers }) => {
        const user = response.data;

        return {
          data: {
            ...user,
            company_ids: companyUsers
              .filter(item => item.user_id === user.id)
              .map(item => item.company_id),
          },
        }
      });
    }

    // Inject user_ids into company
    if (type === 'GET_ONE' && resource === 'companies') {
      return restClient('GET_LIST', 'company_user', defaultOptions).then(({ data: companyUsers }) => {
        const company = response.data;

        return {
          data: {
            ...company,
            user_ids: companyUsers
              .filter(item => item.company_id === company.id)
              .map(item => item.user_id),
          },
        }
      });
    }

    return response;
  });
};
© www.soinside.com 2019 - 2024. All rights reserved.