How do I $watch the Angular-ui's new ui-select (former ui-select2) search string changes?

developer10 picture developer10 · Sep 29, 2014 · Viewed 18.6k times · Source

I noticed that the Angular-UI have discontinued their UI-Select2 directive in favor of the new UI-Select (with multiple themes - select2, bootstrap, selectize).

It looks like this:

<ui-select multiple ng-model="multipleDemo.colors" theme="select2" ng-disabled="disabled" style="width: 300px;">
    <ui-select-match placeholder="Select colors...">{{$item}}</ui-select-match>
    <ui-select-choices repeat="color in availableColors | filter:$select.search">
        {{color}}
    </ui-select-choices>
</ui-select>

<p>Selected: {{multipleDemo.colors}}</p>

Initially my selectbox is supposed to be empty but ready to take typed characters, that is a string of at least 4 characters and then make an API call to retrieve a list of suggested values which are to populate the box. One value will then be chosen, and searching should be repeated as needed.

First I tried $watching the ng-model which in this case is multipleDemo.colors (using this example from the demos). The API call never occurred and then I realized why. The actual model is not changed at all because it only changes when a selection is made (my selectbox is empty so nothing can be selected).

My conclusion is that I should (be able to) $watch what's been added as filter, namely filter: $select.search.

Does anyone know how am I supposed to use that one in my controller?

This:

$scope.$watch('$select.search', function(newVal){
    alert(newVal);
});

doesn't work.

EDIT: For anyone's reference, see this short discussion: Is it possible to add support for custom query function like the select2?

EDIT 2:

I solved this by using $emit from within the directive so the value is available in my controller now. But now I'd like to know how can I override this part of the directive so the directive itself can be left intact so it doesn't break in future updates?

Answer

Chris Bond picture Chris Bond · Nov 6, 2014

Use the refresh attribute on the <ui-select-choices> element to call a function on your scope with $select.search as the parameter:

<ui-select-choices repeat="color in multipleDemo.availableColors | filter:$select.search"
                   refresh="refreshColors($select.search)"
                   refresh-delay="0">
    {{color}}
</ui-select-choices>

Then use the function (refreshColors() in this snippet) to update multipleDemo.availableColors accordingly.

You may also use the refresh-delay attribute to specify how many milliseconds to debounce the function so it is not called too many times in quick succession.

I have also put availableColors on multipleDemo like you have done for multipleDemo.colors, as is recommended.

Reference: ui-select directive wiki under section Examples: Async.