Order search results in react-select - reactjs

When using react-select, search results are ordered alphabetically by default. This is a good default but not so nice if I have an exact match that is not first alphabetically. For example, a user may have the following options:
a_react
b_react
c_react
d_react
react
With these options, the user may search for 'react' and not be any closer to selecting the option that exactly matches the search term. Is there any way to optimize for exact matches?

react-select has a prop if you want to have a custom filter - filterOption.
If you want to show better matches based on what a user queries, use match-sorter in combination with onInputChange of react-select to create a custom filter. Here's a working demo.
There are two select inputs. Type l and observe the difference in suggestions.

In react-select you can pass a filterOption property to change how the filtering works. They provide a nice api to do what you want, which is start matching from the beginning of the string rather than anywhere in the string. That would look something like this
filterOption={createFilter({ matchFrom: "start" })}
where createFilter is imported from react-select

#ron4ex has a great answer here. Just wanted to offer another similar solution as I had 1 big issue with match-sorter.
Issue with match-sorter:
My list is a list of family relationships, e.g. "mother", "mother-in-law"
match-sorter would prioritize mother-in-law over mother as I started typing. Only once it was a full match would it prioritize mother. However, react-select kept the focused option as mother-in-law.
Even if I could fix the default focus issue, I would rather "mot" match to "mother" before "mother-in-law".
Enter new solution: Fuse:
Similar implementation as match-sorter
Fuzzy search with lots of customization options
Default config sorted "mother" over "mother-in-law"
const fuse = new Fuse(relationshipTypes, { keys: ["label"] });
<Select>
onInputChange={inputValue => {
setRelationshipOptions(
fuse.search(inputValue).map(value => value.item)
);
}}
</Select>
notice the map on fuse.search as fuse returns a mutated array with the original values in an item key and a second key being the index. Hence, fuse.search().map

Related

MUI Autocomplete fetch data from request

I have one annoying problem with autocomplete in MUI 5.
I have several autocomplete components that are connected to huge dictionaries. Because of that, I don't insert the entire collection to "option" param in autocomplete, but call API to search in MongoDB when user inputs something.
In dev env when working with some forms (which have these components) I have a little annoying problem. Some of these components have the option multiple and when I have a value there and start looking for another value in console I have this warning.
MUI: The value provided to Autocomplete is invalid.
None of the options match with `{...}`.
You can use the `isOptionEqualToValue` prop to customize the equality test.
Everything works correctly and I have a valid implemented method "isOptionEqualToValue", but because I do not insert the whole dict to option, and when it searches a new value, API filters the collection for the search text.
Autocomplete thinks the values I chose previously are not valid because it is not in the options array, but are valid throughout the collection.
So my question is, can I get rid of this warning or should I do something else?

ID Save and Display Name - material ui multiselect with chips

I am using Material UI Multiple Select based on documentation example. I need to save id of the selected option and show name,
I have tried many ways but nothing helps.
I need to store the id and Display the value. Please help me with your guidance.
Here is my codesandbox link
I was wondering about the same and the only way I found to make it work is by transforming the array to an object.
Here goes the sandbox: https://codesandbox.io/s/material-demo-5cy6p
In it you can see how names is no longer an array but an object with the value of the menu option as a key and the name you want to actual show as the value:
const names = {
1: 'Lorem',
2: 'Ipsum',
}
This way you can access the value(the name) in O(1) time (if you are not familiar with the Big O notation gives this a read: https://en.wikipedia.org/wiki/Big_O_notation), this is way faster than going through the whole array looking for an object with the same id as the one you are mapping.

Conditional dropdowns with react-select and react-final-form field arrays

I'm using react-select with react-final-form and I need to have two selects, where the selected option in the first select dynamically sets the options for the second select. For example, when option One is selected in the first select, the second select gets options One A and One B.
These selects are used in an array. Here is my codesandbox with initial setup https://codesandbox.io/s/react-final-form-field-arrays-e4mm6?fontsize=14.
I've found two similar examples, but I don't know how to adapt them to my use case.
First, I've found this example for react-final-form which sets field's value using createDecorator, but it's used for the value of the field and not the options prop.
Second, I've found this example for react-select which sets options dynamically using state, but I don't know how I can adapt it to my case, considering field arrays.
I would appreciate any help.
Interesting, problem. Here ya go. I created a <PickOptions/> component that watches the first field and provides the options to the second. It also clears the second field when the value of the first changes, which seemed like something you'd want. You could also set it to the first option in the array or something...

React Admin: Can I use another field for <ReferenceInput>, other than "id"?

Is there any way to use a different reference field (other than id) for a ReferenceInput?
For example:
I have a languages resource, which I want to populate using a language_code field.Note, I don't want to use the id field of languages, I want to use the code field.
I have managed to get it to work by using the following:
<ReferenceInput
label="Language code"
source="language_code"
reference="languages"
>
<SelectInput optionText="name" optionValue="code" />
</ReferenceInput>
The only problem with this is that:
After selecting a language from the select input, the ReferenceInput tries to fetch the resource using the code field rather than the id field, which returns a 404 error.
The value stored as the reference to the languages in the resource must be its identifier. Indeed, if you add a ReferenceField in the show view of your resource, how can it fetch the language without its id ?
You have two options here:
make your API support the languages/en route
store the language_id in addition to the language_code in your resource and create a custom ReferenceInput which will return both values after selection
Do we know the underlying reason why we use "id" field for the <ReferenceInput>?
On that note, here's an official explanation from react-admin.
IMO, if we catch that bit from react-admin then we can (try to) use any other field, maybe !
In your case, fetches data, and delegates rendering down to <SelectInput> to which it passes the possible choices as the choices attribute. This works fine since you are able to select a "language".
Are you aware that optionValue="id" is the default?
Two possible solutions:
Remove optionValue="code"
Can you find a way to map your "code" to an "id"? Remember in this case <SelectInput> populates it's choices prop from <ReferenceInput>,choices=[{id='', value=''}, {...}]

Get only one matching row from Solr array

How do I get only a row which matches my query: ?q=taxonomy_ids:1/636/*
Got that result:
Want only: <str>1/636/587</str>
There is no easy way. However, there is a trick, where you use a match highlighter and use those results instead of the results returned from the search itself. You may want to configure PRE/POST highlight tags to empty strings. There was an article on the web about somewhere, but I can't find it again.
The disadvantage is that you get your results twice. Once as docs and once as highlight.
The other option is a custom component that hooks into Lucene's explain structure.

Resources