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

时间:2017-11-28 11:53:10

标签: admin-on-rest

考虑一个我有一个功能性JSON后端和管理员资源companyusercompany_user的情况。

数据如下

公司

  • ID
  • 名称
  • 地址 ...等

用户

  • ID
  • 名称
  • 电话
  • 地址 ...等

company_user

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

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

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

  1. 搜索此用户当前未提及的所有公司(当然有API调用);
  2. company_user集合中添加一行;
  3. 刷新标签

1 个答案:

答案 0 :(得分: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;
  });
};