anubra266 / choc-autocomplete

🏇 Autocomplete Component Package for Chakra UI
https://githubbox.com/anubra266/choc-autocomplete/tree/main/demo
MIT License
395 stars 50 forks source link

Filter options based on label, not value #262

Open mfnash opened 1 month ago

mfnash commented 1 month ago

If the options is array of objects containing value and label properties, I want to filter the options based on the label, because the value contains an ID that shouldn't need to appear in the dropdown. This includes the results shown in the autocomplete, which should also come from the label. Currently, I haven't found a way to change this because the filter and displayed results can only be taken from the value. The value is only used to store the result in the form behind the scenes.

Kysluss commented 1 month ago

Hi @mfnash

Can you post a quick example what you mean? You should be able to filter based on the label by supplying your own filter prop.

adjNoun commented 3 weeks ago

Hey I think I have the same issue. I'm using the AutoComplete to assign a user to task.

A user has a userID and a name. When choosing the user, the dropdown should have just the names visible and the autocomplete should be based off those names. When selecting a user, the input should reflect that name. And in the form, the value used should be the userID. The problem is that autocomplete, and even highlighting of the option, is based off the value of AutoCompleteItem. The AutoCompleteInput also shows this value, which I want to be the userID for use with the form

Here you can see that the autocomplete is not matching with the visible name image

And here you can see that typing the userID matches with the name of the user instead, and selecting that user populates the input with the userID image

Sorry for no code, it's late.

Kysluss commented 3 weeks ago

I think I see what you're saying. So when you select the option, what's displayed in the input is the actual value. Are you using a form library like formik or react-hook-form? The way I've gotten around this in my recent projects is to not bind the value directly to the AutoCompleteInput. Instead, I've used the onSelect prop and called the library's internal setXXXX method. That allowed me to display what I wanted on the input itself while causing my form data to have the value I wanted.

It's a little late at the moment, but I should be able to post an example tomorrow of what I mean.

Kysluss commented 3 weeks ago

@mfnash and @adjNoun ,

I think an example of how to do what you're referring to is in the react-hook-form and formik examples. Below is the code from the react-hook-form demo. Using an array of objects, you can search by either the label or the value prop (try typing the word four into the input). When you select that item, the corresponding label is displayed in the input and not the value.

Sorry if I'm misunderstanding the issue here, but hopefully this helps.

const options = [
  { label: "apple", value: "one" },
  { label: "appoint", value: "two" },
  { label: "zap", value: "three" },
  { label: "cap", value: "four" },
  { label: "japan", value: "five" },
];

function ReactHookFormExample() {
  const { register, setValue, watch, handleSubmit } = useForm({
    defaultValues: { team: "one" },
  });

  const value = watch("team");

  const { onBlur, name } = register("team");
  const onSubmit = data => console.log("data from form", data);

  return (
    <Box border="1px" borderRadius="1em" p={2}>
      <Heading as="h6" align="center">
        React Hook Form
      </Heading>
      <Button onClick={() => setValue("team", "four")}>
        Change Value To four
      </Button>
      <form onSubmit={handleSubmit(onSubmit)}>
        <FormControl>
          <FormLabel>Olympics Soccer Winner</FormLabel>
          <AutoComplete
            onChange={val => setValue("team", val)}
            openOnFocus
            rollNavigation
            listAllValuesOnFocus
            freeSolo
            value={value}
          >
            <AutoCompleteInput variant="filled" name={name} onBlur={onBlur} />
            <AutoCompleteList>
              <AutoCompleteGroup>
                {options.map(option => (
                  <AutoCompleteItem
                    key={`option-${option.value}`}
                    value={{
                      title: `${option.value}`,
                    }}
                    label={option.label}
                    textTransform="capitalize"
                  />
                ))}
              </AutoCompleteGroup>
            </AutoCompleteList>
          </AutoComplete>
          <FormHelperText>Who do you support.</FormHelperText>
        </FormControl>
        <Center>
          <Button type="submit">Submit</Button>
        </Center>
      </form>
    </Box>
  );
}

export default ReactHookFormExample;