What you were expecting:
With <FormDataConsumer>, the <ReferenceInput> to be updated with different choices every time formData (or a particularly defined key) is changing, when we use a filter (eg: filter={{cat_id: formData.cat_id}} )
What happened instead:
The choices are not updated, they always show the initially fetched choices
Steps to reproduce:
I use the following filter to get a subset of the referenced data as choices in the ReferenceInput:
filter={{cat_id: formData.cat_id}}
When changing the cat_id (through a different field in the form), the subCat_id field is not re-fetched with the new filtered value.
Related code:
<FormDataConsumer>
{({formData, ...rest}) =>
formData.cat_id && (
<ReferenceInput label="SUBCATEGORY" source="subCat_id" reference="subCategories" allowEmpty
perPage={100}
filter={{cat_id: formData.cat_id}}
sort={{field: 'name', order: 'ASC'}}
fullWidth
{...rest}
>
<SelectInput optionText="name" />
</ReferenceInput>
)}
</FormDataConsumer>
Other information:
Environment
React-admin version: Latest master, after a related fix with commit 5ee89998b04b54d7b458845e633de522c41bf162
Last version that did not exhibit the issue (if applicable):
I believe that this problem can be solved with 2 actions:
key={formData.cat_id} to the ReferenceInput so that it remounts on every change of the cat_id:{({formData, ...rest}) =>
formData.cat_id && (
<ReferenceInput
key={formData.cat_id}
label="SUBCATEGORY"
// ...all other props here
>
<SelectInput optionText="name" />
</ReferenceInput>
)}
ReferenceInputController so that it always resets the value of the field to null when the component remounts (see last line below):export class ReferenceInputController extends Component {
constructor(props) {
super(props);
const { perPage, sort, filter } = props;
// stored as a property rather than state because we don't want redraw of async updates
this.params = { pagination: { page: 1, perPage }, sort, filter };
this.debouncedSetFilter = debounce(this.setFilter.bind(this), 500);
this.props.change(REDUX_FORM_NAME, this.props.source, null, false, false);
}
UPDATE: This approach fails for editing existing records, as the form value is converted to null. So this approach is a no-go (ignore it), unless there is a better way to handling the edit part.
Another approach that I tried and worked was that I explicitly added a "dependsOnValue" prop (eg: .dependsOnValue = {formData.cat_id}). If this prop value changes, then the code in the controller is doing a refetch plus a "set form value to null" action at componentWillReceiveProps.
componentWillReceiveProps(nextProps) {
if (
this.props.record.id !== nextProps.record.id ||
this.props.dependsOnValue !== nextProps.dependsOnValue
) {
this.fetchReferenceAndOptions(nextProps);
} else if (this.props.input.value !== nextProps.input.value) {
this.fetchReference(nextProps);
}
if (this.props.dependsOnValue !== nextProps.dependsOnValue) {
this.props.change(REDUX_FORM_NAME, this.props.source, null, false, false);
}
}
What do you think?
If any of the approaches is OK to you, please let me know to submit the respective PR. Thanks.
+1
+1
@fzaninotto This is still a problem (needs a workaround, with extra props), may any change be done in the core? Also may I ask if FormDataConsumer is available for the Filters?
Fixed by #2065
Hi it doesn't seem to be working. For this example, the first value selected in SelectInput lang is kept:
<SimpleForm>
<SelectInput label="Langue" source="lang" choices={LANG_LIST} />
<FormDataConsumer>
{({ formData, ...rest }) => formData.lang &&
<ReferenceInput label="Rubrique" source="category" reference="postcategories" filter={{ lang: formData.lang }} {...rest}>
<SelectInput optionText="title" />
</ReferenceInput>
}
</FormDataConsumer>
</SimpleForm>
For this example, the first value selected in SelectInput lang is kept
That's actually a feature :) We always show the selected value
Sorry if i'm not really clear. The only first value is kept. If i change a second time the lang selector, the reference input send api call with in filter value the first value lang.
Can you setup a codesandbox?
The same for me, how can I fix it?
Yes, the fix was incomplete and has been finalized in https://github.com/marmelab/react-admin/pull/2117 which will be released in 2.2.1. In the mean time, add a key prop to the ReferenceInput component:
<FormDataConsumer>
{({ formData, ...rest }) =>
formData.lang && (
<ReferenceInput
key={formData.lang}
label="Category"
source="category_id"
reference="categories"
filter={{ lang: formData.lang }}
{...rest}
>
<SelectInput optionText="title" />
</ReferenceInput>
)
}
</FormDataConsumer>
Hello people. This bug is still exist. How fix it ?
Any updates on this issue? Adding a key prop wouldn't help as I am returning a TextInput inside my FormDataConsumer.
Most helpful comment
Yes, the fix was incomplete and has been finalized in https://github.com/marmelab/react-admin/pull/2117 which will be released in
2.2.1. In the mean time, add a key prop to theReferenceInputcomponent: