Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix <AutocompleteInput> should not use matchSuggestion when in a <ReferenceInput> #8956

Merged

Conversation

slax57
Copy link
Contributor

@slax57 slax57 commented May 30, 2023

Problem

When provided with a matchSuggestion and used in a <ReferenceInput>, <AutocompleteInput> does actually do the filtering twice: once immediately client-side, and then once server-side.
The client-side filtering does not make much sense because it's done only on a subset of the data, and besides it leads to UI flickering when the server-side results arrive.

Solution

Actually this is a bug, we shouldn't call getSuggestions() when used inside a reference, at all.
We already do this to disable MUI's Autocomplete default filtering fn, so I just extended this behavior to getSuggestions().

I also had to adapt the error message warning the user that they can't use optionText without matchSuggestion, to only trigger when not used in a reference. Indeed, in a reference, matchSuggestion should never be called, as it is used for client-side filtering only.

@slax57 slax57 added the RFR Ready For Review label May 30, 2023
@fzaninotto fzaninotto merged commit 6b72346 into master May 31, 2023
10 checks passed
@fzaninotto fzaninotto deleted the fix-AutocompleteInput-matchSuggestion-in-reference branch May 31, 2023 05:29
@fzaninotto fzaninotto added this to the 4.11.1 milestone May 31, 2023
@moulie415
Copy link

This was something I was utilising, I'm using firestore as my db and fetching the data then filtering client side and it was very useful, is there some other way I should be achieving this using the reference input?

@moulie415
Copy link

@slax57 here's my code if it helps to know what I was trying to achieve

import React from 'react';
import {AutocompleteInput} from 'react-admin';

const MyAutoCompleteInput = props => {
  return (
    <AutocompleteInput
      {...props}
      filterToQuery={() => ''}
      matchSuggestion={(filter, suggestion) => {
        return (
          suggestion[props.optionText].toLowerCase().indexOf(filter) !== -1
        );
      }}
    />
  );
};

export default MyAutoCompleteInput;

@slax57
Copy link
Contributor Author

slax57 commented Jun 19, 2023

@moulie415 Yes, if you'd like to enable client-side filtering, you need to provide <AutocompleteInput> directly with a list of choices. You can fetch these choices from your API, e.g. by using useGetList.

@moulie415
Copy link

moulie415 commented Jun 20, 2023

@slax57 thank you for the help, in case anyone else happens to be in my scenario I achieved the functionality I wanted by removing the ReferenceInput, transferring the props I was using for the ReferenceInput to MyAutoCompleteInput and my code ended up looking like this

import React from 'react';
import {AutocompleteInput, useGetList} from 'react-admin';

const MyAutoCompleteInput = props => {
  const {data} = useGetList(props.reference, {
    pagination: {perPage: props.perPage || 200, page: props.page || 1},
  });
  return (
    <AutocompleteInput
      {...props}
      choices={data?.map(item => {
        return {id: item.id, [props.optionText]: item[props.optionText]};
      })}
      filterToQuery={() => ''}
      matchSuggestion={(filter, suggestion) => {
        return (
          suggestion[props.optionText]
            ?.toLowerCase()
            .indexOf(filter?.toLowerCase()) !== -1
        );
      }}
    />
  );
};

export default MyAutoCompleteInput;

@wcmatheusoliveira
Copy link

wcmatheusoliveira commented Dec 5, 2023

Hey team, I've a lot of ReferenceInput across my application using the AutocompleteInput component. Every single autocomplete stop work except for the ones that uses data={CHOICES}. I notice that using the package ra-ui-materialui: 4.9.2 it works but I got some types errors. We've a medium/large application today, move it to use "choices" instead of ReferenceInput would cost us a lot. We're a enterprise customer, let me know what is the best solution to take from here.

This is our dependecies list:

"dependencies": {
"@emotion/react": "11.10.6",
"@emotion/styled": "11.10.6",
"@material-ui/core": "4.12.4",
"@material-ui/icons": "4.11.3",
"@mui/lab": "5.0.0-alpha.152",
"@mui/material": "5.12.0",
"@mui/styles": "5.14.17",
"@mui/x-data-grid": "6.9.2",
"@mui/x-data-grid-generator": "6.11.1",
"@react-admin/ra-calendar": "4.0.1",
"@react-admin/ra-editable-datagrid": "4.2.1",
"@react-admin/ra-enterprise": "6.0.4",
"@react-admin/ra-form-layout": "4.6.2",
"@react-admin/ra-navigation": "4.4.2",
"@react-admin/ra-relationships": "4.2.2",
"@react-admin/ra-tree": "4.2.0",
"@react-keycloak/web": "3.4.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "14.4.3",
"classnames": "2.3.2",
"dayjs": "1.11.9",
"graphql": "16.6.0",
"graphql-tag": "2.12.6",
"jwt-decode": "3.1.2",
"keycloak-js": "18.0.1",
"leaflet": "1.9.3",
"lodash": "4.17.21",
"mui-tel-input": "3.2.2",
"papaparse": "5.4.1",
"pluralize": "8.0.0",
"powerbi-client": "2.22.2",
"powerbi-client-react": "1.4.0",
"prop-types": "15.8.1",
"ra-data-graphql-simple": "4.8.4",
"ra-data-json-server": "4.9.2",
"react": "18.2.0",
"react-admin": "4.15.5",
"react-dom": "18.2.0",
"react-geosuggest": "2.14.1",
"react-image-file-resizer": "0.4.8",
"react-leaflet": "4.2.1",
"react-medium-image-zoom": "5.1.5",
"react-scripts": "5.0.1",
"react-sortable-tree": "2.8.0",
"serve": "14.2.0",
"typescript": "4.9.5",
"use-debounce": "9.0.4",
"web-vitals": "2.1.4"
},
"resolutions": {
"react-hook-form": "7.40.0",
"@types/react": "18.0.34",
"@types/react-dom": "18.0.0",
"@types/react-geosuggest": "2.7.13"
}

@moulie415
Copy link

@wcmatheusoliveira it would probably be more helpful to see a code sample of how you're using ReferenceInput with AutoComplete input

@wcmatheusoliveira
Copy link

<ReferenceInput
      alwaysOn
      label="Customer"
      source="customerId"
      reference="customers"
    >
      <AutocompleteInput  label="Customer" />
</ReferenceInput>

@moulie415
Copy link

moulie415 commented Dec 6, 2023

@slax57 thank you for the help, in case anyone else happens to be in my scenario I achieved the functionality I wanted by removing the ReferenceInput, transferring the props I was using for the ReferenceInput to MyAutoCompleteInput and my code ended up looking like this

import React from 'react';
import {AutocompleteInput, useGetList} from 'react-admin';

const MyAutoCompleteInput = props => {
  const {data} = useGetList(props.reference, {
    pagination: {perPage: props.perPage || 200, page: props.page || 1},
  });
  return (
    <AutocompleteInput
      {...props}
      choices={data?.map(item => {
        return {id: item.id, [props.optionText]: item[props.optionText]};
      })}
      filterToQuery={() => ''}
      matchSuggestion={(filter, suggestion) => {
        return (
          suggestion[props.optionText]
            ?.toLowerCase()
            .indexOf(filter?.toLowerCase()) !== -1
        );
      }}
    />
  );
};

export default MyAutoCompleteInput;

@wcmatheusoliveira I'm not sure about the structure of you customers data but if for example your customer object contained a "customerName" that you wanted to display in the drop down then if you wanted to use my example above then your could do use it like this

    <MyAutoCompleteInput
      label="Customer"
      source="customerId"
      reference="customers"
      optionText="customerName"
    />

For your use case you may not want to do what I did with the filterToQuery and matchSuggestion props though

@slax57
Copy link
Contributor Author

slax57 commented Dec 6, 2023

@wcmatheusoliveira Since you are an Enterprise customer you have access to our dedicated support desk.
I believe you have already opened a ticket there (which we answered), so feel free to continue the discussion there if you need further help, we'll do our best to assist you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFR Ready For Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants