xcash / bootstrap-autocomplete

Bootstrap Autocomplete
MIT License
168 stars 72 forks source link

Add other parameters to request URL #94

Open daniol opened 3 years ago

daniol commented 3 years ago

Currently its not easily possible to supply other dynamic arguments to the URL, based maybe on other forms fields, in order to return data based in other parameters apart of the search term. A "get URL" event would be helpful. It could get the original url (set via data- or settings) and modify it (optionally).

Example:

Number: <input class="form-control" type="number" id="inputNumber" value="1" /><br/>
Search: <input class="form-control" type="text" data-url="myurl" autocomplete="off" id="inputAutocomplete" /><br/>

<script>
$('#inputAutocomplete').autoComplete({
    events: {
        getUrl: function ( originalUrl ) {
            return originalUrl + "?number=" + $('#inputNumber').val();
        }
   }
});
</script>

The ajax url will be finally for example: "myurl?number=1&q=mytext".

Another option would be to refresh internally the URL set with "data-url" before making the request.

adriano-ghezzi commented 3 years ago

It is an essential feature for example when chaining multiple select. I prefer the option to have a callback to modify the url. Thanks

xcash commented 3 years ago

Well, actually you could already customize all the request flow using existing events. However I'll look into this. Perhaps the most elegant solution here is changing resolverSettings.url to a function | string type.

adriano-ghezzi commented 3 years ago

well I tried to implement custom resolver

first I notice an error in documentation

the call callback(res.results) should be callback(res)

I can get the right result

The dropdown is shown as expected

The problem is that the event
autocomplete.select is never triggered

here is the handler

$('#regione').on('autocomplete.select', function (evt, item) { chainedClass.selectChanged(evt, item) });

and here the resolver


$('#regione').autoComplete({
            resolver: 'custom',
            events: {
                search: function (qry, callback) {
                    // let's do a custom ajax call
                    console.log("search="+qry);
                    $.ajax(
                        'http://localhost:8000/data_test.php?type=regione&action=get',
                        {
                            data: { 'qry': qry}
                        }
                    ).done(function (res) {
                        // callback(res.results)
                        callback(res)
                    });
                }
            }
        });

let me say that every thing is working well if I use basic resolver

Thanks for any help.

xcash commented 3 years ago

Hi @adriano-ghezzi

callback(res.results) is an example. In my test file I have a first level results key.

No errors and no event triggered is really strange.

monetschemist commented 3 years ago

I wonder if anyone has managed to find a working approach to this?

In case a bit more complete description helps:

In my case, I have a pair of fields. The first field is a standard enhanced with autoComplete.

The idea is that the URL of the autoComplete

By way of example, the first field could be "country", the second "stateOrProvince". Then if the user selects for example Canada as the country, the "canadaProvinces" table will be searched.

I've tried messing around in quite a number of ways with resolverSettings.url but it seems that this is read once, when autoComplete() is called.

I have a kind of unclear idea that I could somehow cause the url to be rewritten in the searchPre event, but I'm not having any luck making that (nor pretty much any other solution I've tried) work.

I wonder if someone could perhaps add this kind of example to the examples page.

Thanks very much in advance!

xcash commented 3 years ago

HI @monetschemist

The way to do this is simple. You only need to implement the search event.

$('.advancedAutoComplete').autoComplete({
                resolver: 'custom',
                events: {
                    search: function (qry, callback) {
                        // let's do a custom ajax call
                        $.ajax(
                            'testdata/test-dict.json',
                            {
                                data: { 'qry': qry}
                            }
                        ).done(function (res) {
                            callback(res.results)
                        });
                    }
                }
            });
monetschemist commented 3 years ago

@xcash thank you very much for this. For the sake of anyone else who comes here and reads this, I'm going to elaborate on what specific things I did to follow your approach to a working solution.

First, the URL (shown above as 'testdata/test-dict.json'). In my case I have call to my (Grails) controller "report", action "descriptionFinder", with a parameter "subject" that I set as the value of the related dropdown, whose id is searchClass. So my URL looks like this:

'report/descriptionFinder?subject=' + $('#searchClass :selected').val()

And that works just fine. I note that, as I said in my first question, I tried a similar thing in resolverSettings.url but that doesn't work, in the sense that changing the value in the related dropdown has no visible effect.

Second, with respect to the data object, the rest of my code uses the default tag 'q' rather than 'qry' so my data object ends up looking like

data: { 'q': qry }

Third, as @adriano-ghezzi mentions above,

calback(res.results)

must be changed to

callback(res)

Now all works quite well; thanks very much again for the pointer to the solution! I should track down the throttling business mentioned in the documentation with respect to the custom resolver...

xcash commented 3 years ago

Hi @monetschemist

The data attribute is a javascript object.

You could simply add your variables to that object and let jquery urlencode correctly the query string. In your solution if you have an = or a ? or a & in your searchClass you will end up with uncorrect url.

Try something like this:

data: { subject: $('#searchClass :selected').val(), q: qry  }

And leave the url clean report/descriptionFinder

monetschemist commented 3 years ago

@xcash thank you yet again, this works perfectly!

In my specific case I'm using Grails .gsp markup to generate the URLs on the server side so it's especially nice to be able to separate the front-end parameters from the back-end markup generators.

Really, really useful info!

gizmotronic commented 3 years ago

This is all great info. Thank you, @xcash @adriano-ghezzi @monetschemist! I was able to adapt this to my use case quite easily, including some basic throttling.

I can't find a way to clear the search results if I change one of the inputs that I use to construct my search. It's easy enough to clear the input:

$('.advancedAutoComplete').autoComplete('clear');

But, when it's focused again, the previous search results show. Am I missing something?

gizmotronic commented 3 years ago

I realize it's really bad form to reply to one's own questions, but I stumbled upon the answer to my question accidentally. Instead of clearing the input, I simply showed the autocomplete field again when I detected a change to the other input:

$('otherInput').on('change', function () {
  $('.advancedAutoComplete').autoComplete('show');
}