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

Vue 3 Custom renderer state only changes on blur #870

Open
a47ae opened this issue Jan 17, 2022 · 6 comments
Open

Vue 3 Custom renderer state only changes on blur #870

a47ae opened this issue Jan 17, 2022 · 6 comments

Comments

@a47ae
Copy link

a47ae commented Jan 17, 2022

Description

When creating a custom renderer using Vue 3, the state only updates on the input change event and not during input.
So the state gets only updated when the user moves focus from the input and then moves focus back to the input.

Reproduction

Codesandbox →

Steps

  1. Focus the input
  2. Enter foo
  3. Tab out of the input
  4. Re-focus the input
  5. See the panel open with the suggestion foo

Expected behaviour

  1. Focus the input
  2. Enter foo
  3. See the panel open with the suggestion foo without moving focus out of the input

Environment

  • OS: macOS Big SUr
  • Browser: Chrome 97.0.4692.71
  • Autocomplete version: 1.5.1
@a47ae
Copy link
Author

a47ae commented Feb 7, 2022

Okay I think I found the issue here :D

When using React, the onChange event is not the browser change event, but basically the input event (https://stackoverflow.com/a/40003179). When passing the autocomplete instance getInputProps result to Vue and binding this to an input Element, the onChange gets used as a real change event listener, when instead it should be an input event listener.

In @algolia/autocomplete-js this gets handled by utils/setProperties.ts which contains dictionary to normalize the event names and there onChange gets translated into onInput.

So if one wants to use @algolia/autocomplete-core with Vue, either one should use import { setProperties } from '@algolia/autocomplete-js/dist/esm/utils/setProperties' and not bind the values to the input element, or one should remove the onChange (the value binding must also be removed) and replace it like so:

const inputProps = computed(() => {
  const { onChange, value, ...rest } = autocomplete.value.getInputProps({
    inputElement: inputElement.value,
    autofocus: true,
  });

  return {
    onInput: onChange,
    ...rest,
  };
});

Maybe it would be nice to mention this in the docs somewhere because if you are not using React this may be a bit confusing.

@Haroenv
Copy link
Contributor

Haroenv commented Feb 7, 2022

That's a great find @a47ae, thanks for sharing your solution. Does anything need to be updated on the documentation, or is the original issue coming from code you wrote on your side?

@a47ae
Copy link
Author

a47ae commented Feb 7, 2022

Hey @Haroenv, I think it would be really great to have a Vue version of the creating a richt text box page. There is already a section on using autocomplete-js with Vue so having one on autocomplete-core would be really useful and a great learning resource.

If a Vue implementation is not feasible to maintain then in my opinion it should mention somewhere on the creating a custom renderer page or the createAutocomplete api reference page that the getInputProps getter returns the props named in a way that is intended to be consumed by React and specifically that one should use onInput when using other libraries than React.

@Haroenv
Copy link
Contributor

Haroenv commented Feb 7, 2022

Thanks, I'll leave this issue open so we can take the time to address those suggestions

@jnpwebdeveloper
Copy link

Thank you @a47ae. What great find. It was driving me nuts.

I was trying to figure out why this was not working in Preact either. The React example worked just fine.

I followed the custom renderer instructions and also experienced the same issues where it wasn't mapping to the correct handler in Preact's case also being onInput. This resulted in the autocomplete only working on blur or when pressing enter for me.

Here is adapted solution for Preact in case anyone else that may come across this.

const inputProps = useMemo(() => {
    const { onChange, value, ...rest } = autocomplete.getInputProps({
      inputElement: inputRef.current,
      autofocus: true,
    });

    return {
      onInput: onChange,
      ...rest,
    };
  }, [autocomplete.value, inputRef.current]);

The docs clearly state you can use any framework. So mentioning this on the custom renderer instructions would make a lot of sense.

@slavarazum
Copy link

One day of debugging brought me here. @a47ae Thanks for the notice.
How do you make attributes reactive returned from: getRootProps, getInputProps etc. ? During searching, some attribute values should be changed, such as aria-expanded or aria-selected.

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

No branches or pull requests

4 participants