autoComplete.js icon indicating copy to clipboard operation
autoComplete.js copied to clipboard

Make current element available in src callback

Open Radiergummi opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe. I'm creating multiple autocomplete elements on the page dynamically. They receive suggestions from a JSON endpoint which is resolved at template rendering time. To pass the proper endpoint to the autocomplete input, I would like to do the following:

<input type="text" class="autocomplete" data-suggestions-endpoint="{{ route('foo.bar') }}">

In the next step, I would configure AutoComplete:

const autoCompleteJS = new autoComplete( {
    selector: '[data-suggestions-endpoint]',
    data: {
        src: query => fetch( url ).then(r => r.json())
    }
} );

Alas, there's no way to get access to the data property.

Thoroughly Describe the solution you'd like It would be great if the current element were passed to the query callback as the second parameter:

const autoCompleteJS = new autoComplete( {
    selector: '[data-suggestions-endpoint]',
    data: {
        src: (query, element) => fetch( element.dataset.suggestionsEndpoint )
                                     .then(r => r.json())
    }
} );

Please provide a few use cases for this feature

  1. Configuring dynamic endpoints, as above
  2. Bridging between server-side rendered templates, and frontend applications - that way, autocomplete could be configured using declarative attributes on the input instead of inline JS
  3. Checking the current state of the input element; you might want to abort searching if the user leaves the input field (I'll admit this one is a little convoluted)

Please Describe alternatives you've considered Obviously, binding every element by itself:

const instances = Array.from( document.querySelectorAll(
    '[data-suggestions-endpoint]'
) ).map(element => new autoComplete( {
    selector: () => element,
    data: {
        src: (query) => fetch( element.dataset.suggestionsEndpoint )
                                     .then(r => r.json())
    }
} ) );

This works, but has the drawback of creating several instances instead of a single one.

Additional context

Radiergummi avatar Feb 16 '22 11:02 Radiergummi

@TarekRaafat What do you think about this issue? If this is something we want for the project I would gladly provide a PR for that. I definitely see the use case and I also had a case like this already where this feature would have been useful.

Brainshaker95 avatar Oct 09 '22 16:10 Brainshaker95

+1

I tried the alternative @Radiergummi (thanks for that!) proposed, but could not get it to work.

Uncaught (in promise) TypeError: element is undefined

in line src: (query, element) => fetch( element.dataset.suggestionsEndpoint )

jonnsn avatar Jan 02 '23 13:01 jonnsn

I tried the alternative @Radiergummi (thanks for that!) proposed, but could not get it to work.

Uncaught (in promise) TypeError: element is undefined

Sorry, that was copy pasted sloppily! If you remove the second parameter element from the callback, it will use the instance from the parent scope, and work.

Radiergummi avatar Jan 03 '23 16:01 Radiergummi