emeraldjava
emeraldjava

Reputation: 11200

Angular typeahead which filters by multiple json object fields

I have a webpage which has an autocomplete component using Jquery to a typeahead component in Angular JS. The data structure is the same

runners=
    [{"id":"8425","value":"8425","label":"Alan Adams"},
    {"id":"4559","value":"4559","label":"David Adams"},
    {"id":"7564","value":"7564","label":"Dessie Adams"}]

the idea is that the user can enter the runner's 'value' or 'label' value (ie their membership id or name) and get the whole runner object at the end.

The jQuery autocomplete component does this

jQuery("#memberfilter").autocomplete({
    source: bhaa_members,
    minLength: 3,
    source: function (request, response) {
        var matcher = new RegExp(jQuery.ui.autocomplete.escapeRegex(request.term), "i");
        response(jQuery.grep(bhaa_members, function(value) {
            return matcher.test(value.label) || matcher.test(value.value);
        }));
    },

using a matcher to check the 'label' or the 'value'.

In my angular version

<div class='container-fluid typeahead-demo' ng-controller="memberTypeaheadCtrl">
<h4>Search for Member</h4>
<input type="text" 
    ng-model="runnerSelected"
    uib-typeahead="runner.label for runner in runners | filter:$viewValue | limitTo:8"
    class="form-control"/>
<pre>Member: {{runnerSelected | json}}</pre>

This allows me to filter by 'label', and i added this enable search by 'value'

 uib-typeahead="runner.value as runner.label for runner in runners | filter:$viewValue | limitTo:8"

but in each case, i only get a 'label' or 'value' and not the runner object i need?

EDIT - Answer

After a bit more digging i found an answer here https://stackoverflow.com/a/28751281/55794 which uses 'typeahead-on-select' to filter on the second object attribute

<input type="text"
     ng-model="runnerSelected"
     uib-typeahead="runner as runner.label for runner in runners | filter:$viewValue | limitTo:8"
     typeahead-editable="false"
     typeahead-on-select="model=$item.value"
     typeahead-loading="loadingLocations"
     typeahead-no-results="noResults"
     class="form-control"/>

I can now enter a 'label' or a 'value' and always get a runner.

Upvotes: 2

Views: 2791

Answers (1)

JB Nizet
JB Nizet

Reputation: 691715

You're mistaken. Both filter the array, using the $viewValue as the filter. Since it's a string, it will look for a runner which has any of its attributes containing the entered value. Read the documentation of the angular filter filter to understand how it works. You can of course use enother filter than just $viewValue if you need a different way of matching the desired runners.

To have the runner as your model, all you need is

runner as runner.label for runner in runners | filter:$viewValue | limitTo:8

Upvotes: 2

Related Questions