-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Expand file tree
/
Copy pathReferenceArrayInputBase.tsx
More file actions
117 lines (111 loc) · 3.86 KB
/
ReferenceArrayInputBase.tsx
File metadata and controls
117 lines (111 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import * as React from 'react';
import { InputProps } from '../../form/useInput';
import {
useReferenceArrayInputController,
type UseReferenceArrayInputParams,
} from './useReferenceArrayInputController';
import { ResourceContextProvider } from '../../core/ResourceContextProvider';
import { ChoicesContextProvider } from '../../form/choices/ChoicesContextProvider';
import { RaRecord } from '../../types';
import { ChoicesContextValue } from '../../form';
/**
* An Input component for fields containing a list of references to another resource.
* Useful for 'hasMany' relationship.
*
* @example
* The post object has many tags, so the post resource looks like:
* {
* id: 1234,
* tag_ids: [ "1", "23", "4" ]
* }
*
* ReferenceArrayInputBase component fetches the current resources (using
* `dataProvider.getMany()`) as well as possible resources (using
* `dataProvider.getList()`) in the reference endpoint. It then
* delegates rendering to its child component, to which it makes the possible
* choices available through the ChoicesContext.
*
* Use it with a selector component as child, like `<SelectArrayInput>`
* or <CheckboxGroupInput>.
*
* @example
* export const PostEdit = () => (
* <Edit>
* <SimpleForm>
* <ReferenceArrayInputBase source="tag_ids" reference="tags">
* <SelectArrayInput optionText="name" />
* </ReferenceArrayInputBase>
* </SimpleForm>
* </Edit>
* );
*
* By default, restricts the possible values to 25. You can extend this limit
* by setting the `perPage` prop.
*
* @example
* <ReferenceArrayInputBase
* source="tag_ids"
* reference="tags"
* perPage={100}>
* <SelectArrayInput optionText="name" />
* </ReferenceArrayInputBase>
*
* By default, orders the possible values by id desc. You can change this order
* by setting the `sort` prop (an object with `field` and `order` properties).
*
* @example
* <ReferenceArrayInputBase
* source="tag_ids"
* reference="tags"
* sort={{ field: 'name', order: 'ASC' }}>
* <SelectArrayInput optionText="name" />
* </ReferenceArrayInputBase>
*
* Also, you can filter the query used to populate the possible values. Use the
* `filter` prop for that.
*
* @example
* <ReferenceArrayInputBase
* source="tag_ids"
* reference="tags"
* filter={{ is_public: true }}>
* <SelectArrayInput optionText="name" />
* </ReferenceArrayInputBase>
*
* The enclosed component may filter results. ReferenceArrayInputBase create a ChoicesContext which provides
* a `setFilters` function. You can call this function to filter the results.
*/
export const ReferenceArrayInputBase = <RecordType extends RaRecord = any>(
props: ReferenceArrayInputBaseProps<RecordType>
) => {
const { children, filter = defaultFilter, reference, render, sort } = props;
if (children && React.Children.count(children) !== 1) {
throw new Error(
'<ReferenceArrayInputBase> only accepts a single child (like <AutocompleteArrayInput>)'
);
}
if (!render && !children) {
throw new Error(
"<ReferenceArrayInputBase> requires either a 'render' prop or 'children' prop"
);
}
const controllerProps = useReferenceArrayInputController({
...props,
sort,
filter,
});
return (
<ResourceContextProvider value={reference}>
<ChoicesContextProvider value={controllerProps}>
{render ? render(controllerProps) : children}
</ChoicesContextProvider>
</ResourceContextProvider>
);
};
const defaultFilter = {};
export interface ReferenceArrayInputBaseProps<RecordType extends RaRecord = any>
extends InputProps,
UseReferenceArrayInputParams<RecordType> {
children?: React.ReactNode;
render?: (context: ChoicesContextValue<RecordType>) => React.ReactNode;
}