考虑一个我具有功能性JSON后端的情况,以及Admin-Rest Resources company
,user
和company_user
。
数据如下
公司
- id
- 名称
- 地址...等。
用户
- id
- 名称
- 电话
- 地址...等。
company_user
- id
- company_id(参考公司)
- USER_ID(参考用户)
- 位置...等。
拥有company_user
资源类型的A 单独的顶级资源视图非常容易;但是,每个用户和每个公司都应该在user
的选项卡或company
资源视图上确实可以编辑。
因此出现了问题:如何为user
资源创建一个选项卡,我可以在其中列出当前的company
-References(company_user
行),但是在同一选项卡中,我需要一种理智的方法来执行以下功能:
- 搜索本用户当前未提及的所有公司(当然有一个API呼吁);
- 将行添加到
company_user
集合和; - 刷新标签
处理这种关系的最简单方法是在模型上提供一个额外的领域,以作为关系的代表。
例如,从用户那里我们需要查看他的公司:公开一个新的字段user.company_ids
。该字段不必在数据库中,您的API或代理可以列出此字段中的相关公司ID,并且为了写请求,请使用它来创建,更改或删除关系。
实现了此字段后,adman-on-on-on-on-on-on-on-on-n-pers on th-p>非常易于配置。我制作了一个完全有效的片段: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;
});
};