chowwy
chowwy

Reputation: 1126

jqueryui autocomplete filter results (from remote datasource ) that "begin with" input

I'm using jquery autocomplete with multiple results and a remote datasource. I'm able to pull the data remotely and select multiple results. But the results list doesn't update based on the first 2 characters input, and the jQueryUI documentation is thin on this issue.

I've researched around, and found this answer here on SO and want to integrate it with the rest of my function, but it doesn't update the results list. Independently, the SO answer works fine, but not when integrated with multiple results and a remote datasource.

From the autocomplete/remote source/multiple function (truncated). This part works fine:

.autocomplete({
                source: function( request, response ) {                            
                     $.ajax({
                        url: "/controller/myfunction",
                        dataType: "json",
                        data: request,
                        success: function(data){
                        if(data.response == 'true') {
                            response(data.message);
                            }
                        }
                    });
                },

Possible solution on SO: (works fine independently, but not with the jquery/remote/multiple code):

var wordlist= [ "about", "above", "within", "without"];

$("#input1").autocomplete({
    source: function(req, responseFn) {
        var re = $.ui.autocomplete.escapeRegex(req.term);
        var matcher = new RegExp( "^" + re, "i" );
        var a = $.grep( wordlist, function(item,index){
            return matcher.test(item);
        });
        responseFn( a );
    }
});

I need to integrate this solution with my code.

Upvotes: 5

Views: 12501

Answers (5)

Amit Garg
Amit Garg

Reputation: 3907

 $("#certi_name").autocomplete({
                source: "/controller/myfunction",
                minLength: 2,
                select: function(event, ui) {
                    $('#certi_name').val(ui.item.value);
                    $('#certi_id').val(ui.item.id);

                }
            });

Here is my function. I am using it and working fine.

function certificationsAction()
    {
        $cert_obj = new Model_Certification();
        $obj=$this->getRequest();
        $term=$obj->getParam('term');//You will get passing keyword with the name term
        if($term)
        {
            $ins_arrs=$cert_obj->getMatchingCertifications($term);
            $return_arr = array();
            foreach($ins_arrs as $ins)
            {
                $row_arr['id']=$ins['certification_id'];
                $row_arr['value']=$ins['certification_name'];
                array_push($return_arr, $row_arr);
            }
            echo json_encode($return_arr);die;
        }

    }

Upvotes: 0

Mahyar
Mahyar

Reputation: 681

As you are using $.ajax with json dataType then your data.message is an Array which you can filter it by removing unnecessary items.
assuming the ajax msg Array has been built from below sample json,

{"id":"Nycticorax nycticorax","label":"Black-crowned Night Heron","value":"Black-crowned Night Heron"},{"id":"Ardea purpurea","label":"Purple Heron","value":"Purple Heron"},{"id":"Circus cyaneus","label":"Hen Harrier","value":"Hen Harrier"},{"id":"Alcedo atthis","label":"Common Kingfisher","value":"Common Kingfisher"},{"id":"Oxyura leucocephala","label":"White-headed Duck","value":"White-headed Duck"},{"id":"Oenanthe oenanthe","label":"Northern Wheatear","value":"Northern Wheatear"},{"id":"Tadorna tadorna","label":"Common Shelduck","value":"Common Shelduck"},{"id":"Ardea cinerea","label":"Grey Heron","value":"Grey Heron"},{"id":"Ficedula hypoleuca","label":"Eurasian Pied Flycatcher","value":"Eurasian Pied Flycatcher"},{"id":"Motacilla flava","label":"Blue-headed Wagtail","value":"Blue-headed Wagtail"},{"id":"Muscicapa striata","label":"Spotted Flycatcher","value":"Spotted Flycatcher"},{"id":"Accipiter gentilis","label":"Northern Goshawk","value":"Northern Goshawk"}

so what we want is to check 'value's if each begins with the entered term.
you can simply replace your autocomplete code with this one:

.autocomplete({
    source: function( request, response ) {                            
            $.ajax({
            url: "/controller/myfunction",
            dataType: "json",
            data: request,
            success: function(data){
                if(data.response == 'true') {
                    var t = true;
                    var i = 0;
                    var ptrn = new RegExp("^" + request.term, "i");
                    while (t) {
                        if (!ptrn.test(data.message[i].Name)) {
                            data.message.splice(i, 1)
                        } else {
                            i++
                        };
                        if (i == data.message.length) {
                            t = false;
                        }
                    }
                    response(data.message);
                }
            }
        });
    },
    ...
});

Upvotes: 1

Snivs
Snivs

Reputation: 1125

Optimally, it should be the controller that delivers the filtered data in JSON. I suggest you better try filtering the data in the controller rather than in the view. Of if your application is MVC-oriented, you should keep all the querying and filtering inside of the model used within the controller action you specify. I do think the usage of AJAX (Asynchronous Javascript and XML) should be used to pass on as much load to the server as possible. so, your view code would be rather simple

var wordlist= [ "about", "above", "within", "without"];

$("#input1").autocomplete({
    source: 'url-to-controller/myAction', //Notice I'm using a string
    minLength: 2
});

Autocomplete|jQuery Ui - source states that:

... When a string is used, the Autocomplete plugin expects that string to point to a URL resource that will return JSON data. It can be on the same host or on a different one (must provide JSONP). The Autocomplete plugin does not filter the results, instead a query string is added with a term field, which the server-side script should use for filtering the results. For example, if the source option is set to "http://example.com" and the user types foo, a GET request would be made to http://example.com?term=foo. The data itself can be in the same format as the local data described above.

Based on the above, you could modify your controller action so it uses the term GET request so it is used to filter the data in the query.. Be sure to let me know how it goes.

Upvotes: 1

jk.
jk.

Reputation: 14435

From jQuery UI Autocomplete: Search from Beginning of String you can try:

$("#YOUR_TEXT_INPUT").autocomplete({
    source: function(req, response) { 
       $.ajax({
        url: "/controller/myfunction",
        dataType: "json",
        success: function( data ) {
            var re = $.ui.autocomplete.escapeRegex(req.term);
            var matcher = new RegExp( "^" + re, "i" );
            response($.grep(data, function(item){return matcher.test(item.value);}) );
            }
        });
     },
      minLength: 2,
      select: function(event, ui) {
          //custom select function if needed
       }
    });

Upvotes: 3

Tom Dalling
Tom Dalling

Reputation: 24125

jQuery autcomplete sends what the user has typed in as a HTTP parameter, so you can use that to alter the results that you fetch from the DB.

Here is an example (in CakePHP). It gets the "term" parameter, which contains what the user typed in, and it uses that to generate the DB query.

Upvotes: 1

Related Questions