PUGX / PUGXAutoCompleterBundle

Add an autocomplete field to your Symfony forms
GNU Lesser General Public License v3.0
93 stars 38 forks source link

jQuery-UI scrip does not work because of wrong Ajax parameter names 'id' and 'text' #41

Closed vctls closed 7 years ago

vctls commented 7 years ago

I was trying to use the bundle in my project, and couldn't get it working with jQuery-UI. So I downloaded the demo project, changed the libraries and .js file to jQuery-UI, and got the same symptoms.

With jQuery-UI versions 1.12.1: firefox_2016-12-22_18-07-41 1.11.4: firefox_2016-12-22_18-09-40 1.10.4: firefox_2017-01-03_09-54-28

It does not seem to be a CSS issue since all my stylesheets are loading fine. The AJAX request also works and is not empty. The HTML <li> elements are empty, though.

vctls commented 7 years ago

Ok, found the answer here: http://stackoverflow.com/questions/4234455/jquery-autocomplete-not-working-with-json-data

When using jQuery-UI, the id and text parameters in the JSON search template must be changed to value and label, like this:

[{% for author in authors -%}
    {{ {value: author.id, label: author.__toString}|json_encode|raw }}
    {%- if not loop.last %},{% endif -%}
{%- endfor %}]
vctls commented 7 years ago

Oh, and by the way: the search parameter sent in the ajax request is term form jQuery-UI, instead of q, so that must be changed as well in the controller:

$qs = $request->query->get('term');
vctls commented 7 years ago

Actually, this issue breaks the autocompleter-jqueryui.js script. The select callback from the autocomplete method should read

$this.val(ui.item.value);

instead of

$this.val(ui.item.id);
garak commented 7 years ago

I tried it, but I'm getting the id of the selected option, not its label. Indeed, I also tried with $this.val(ui.item.label); instead of $this.val(ui.item.value);, but I keep getting the value :disappointed:

vctls commented 7 years ago

Did you change the template?

garak commented 7 years ago

I changed search.json.twig, using the content you mentioned above (value instead of id and label instead of text)

vctls commented 7 years ago

That's weird. I don't remember changing anything else. I just tried on the demo project and it worked. Should I push or copy the code somewhere?

garak commented 7 years ago

I'm trying using https://github.com/garak/AutoCompleterSandbox, where I altered search.json.twig (as mentioned above) and changed by hand autocompleter-jqueryui.js in vendor (as you suggested). You can swap to jquery UI by pasasing jqui=1 in "new" page (e.g. /new-book?jqui=1)

vctls commented 7 years ago

Just to be sure: what is the expected behaviour? With jQuery-UI, the field is a text input, so I understand we're using the hidden field to store the ID, while the "fake" input, on which the autocompleter is called, is supposed to display the text value? Is that right?

garak commented 7 years ago

Yes

vctls commented 7 years ago

Got it. You need to preventDefault() on the select event.

$fakeInput.autocomplete({
    source: settings.url_list  + "?jqui=1",
    select: function (event, ui) {
        event.preventDefault();
        // Set the real hidden input to ID number.
        $this.val(ui.item.value);
        // Set the fake input value to the corresponding text value.
        $(this).val(ui.item.label);
        if (settings.on_select_callback) {
            settings.on_select_callback($this);
        }
    },
    minLength: settings.min_length
});
garak commented 7 years ago

It's even worse: it's not updating value at all :disappointed:

vctls commented 7 years ago

Huh. This is confusing. Let me clean this up a bit...

garak commented 7 years ago

OK, the "new" action is working for me now. Now I miss the "edit" action, where I see the id of the numeric id of the author, instead of the name

vctls commented 7 years ago

Found it: There's a small difference between autocompleter-select2.js and autocompleter-jqueryui.js:

// autocompleter-select2.js
$.ajax({
    url: (settings.url_get.substring(-1) === '/' ? settings.url_get : settings.url_get + '/') + $this.attr('value'),
    success: function (name) {
        val = name;
        $fakeInput.select2('val', name);
    }
});
// autocompleter-jqueryui.js
$.ajax({
    url:     settings.url_get + $this.val(),
    success: function (name) {
        $fakeInput.val(name);
    }
});

Change the url parameter and everything works as expected.