7

With React Admin it is possible to add Filters to a List component. An example of this can be seen in the demo: https://marmelab.com/react-admin-demo/#/commands

user search filters in List

The code for this particular component: https://github.com/marmelab/react-admin/blob/master/examples/demo/src/orders/OrderList.js

const OrderFilter = withStyles(filterStyles)(({ classes, ...props }) => (
<Filter {...props}>
    <SearchInput source="q" alwaysOn />
    <ReferenceInput source="customer_id" reference="customers">
        <AutocompleteInput
            optionText={choice =>
                `${choice.first_name} ${choice.last_name}`
            }
        />
    </ReferenceInput>
    <DateInput source="date_gte" />
    <DateInput source="date_lte" />
    <TextInput source="total_gte" />
    <NullableBooleanInput source="returned" />
</Filter>));

...

const OrderList = ({ classes, ...props }) => (
<List
    {...props}
    filterDefaultValues={{ status: 'ordered' }}
    sort={{ field: 'date', order: 'DESC' }}
    perPage={25}
    filters={<OrderFilter />}
>
    <StyledTabbedDatagrid />
</List>
);

However, I can't figure out to add the same functionality to a ReferenceManyField. In the demo website this would for example be the Orders tab for a customer Edit component. Is there a way to configure a Filter component for the ReferenceManyField?

Orders tab

Bas de Raad
  • 556
  • 1
  • 6
  • 15

3 Answers3

3

probably you already found the right answer, but for those who still have this problem. Here is a simple solution. Just use List inside you ReferenceManyField.

const MyFilter = (props) => (
    <Filter {...props}>
        <ReferenceInput
            label="MyFilter"
            source="wallet"
            reference="wallets"
            sort={{ field: 'name', order: 'ASC' }}
            filterToQuery={searchText => ({ name: searchText })}
            allowEmpty={true}
            alwaysOn
        >
            <AutocompleteInput optionText="name" />
        </ReferenceInput>
    </Filter>
);

<ReferenceManyField
    label={false}
    reference="wallets"
    target="user"
>
   <List filter={{ user: record.id}} filters={<MyFilter />}>
      <Datagrid {...props}>         
         <ReferenceField source="vendor" resource="vendors" reference="vendors">
            <TextField source="name"/>
         </ReferenceField>
      </Datagrid>
   </List>
</ReferenceManyField>
Mattin
  • 94
  • 5
  • Thanks for sharing this answer @Mattin. I did notice the moment the List component is injected, the ReferenceManyField target value is ignored. Your code has a { user: record.id } to share the filter, but record is always empty. Is there a way around that? – darren Jan 01 '21 at 22:28
  • Thanks. It was the lack of `alwaysOn` that was causing it to not show for me! – Matt Fletcher Nov 19 '21 at 09:47
0

You can use ListBase for this, the change was added in 3.10+ versions.

<ReferenceManyField
    reference="some-reference"
    target="some-target">
    <ListBase syncWithLocation={true}>
        <ListToolbar
            filters={<YourFilter />}
            actions={<ListActions  hasCreate={true}/>}
        />
        <Datagrid>
            ///etc...
        </Datagrid>

        <Pagination/>
    </ListBase>
</ReferenceManyField>
Jama A.
  • 15,680
  • 10
  • 55
  • 88
0

You can use ListBase as the above answer, but when using ListBase, it ignores the target field in the ReferenceManyField.Therefore you need to give a filter to that.

    const DataFilter = (props) => (
         <Filter {...props}>
             <TextInput label="Search by DataCode" source="id" alwaysOn />
          </Filter>
     );

        <ReferenceManyField
          reference="reference"
          target="targetRef"
          filter={{ targetRef: props.id }}
        >
          <ListBase {...props}  >
            <ListToolbar
              filters={<DataFilter />}
            />
            <Datagrid>
             //datagrid fields
          </Datagrid>
          </ListBase>

        </ReferenceManyField>