Letting the user add a new option besides searching and selecting

We are going to see how we can extend the ui-select control to allow the following:

adding new options dynamically (besides searching and selecting)

adding a custom clear button (to remove the current selection)

Use the links below to hack around.

Demo | Source

Follow me on Twitter for latest updates @gerardsans.

👮 Disclaimer: this code is kind of hacky use responsibly.

Introduction to ui-select

ui-select is the AngularJS-native version of Select2 and Selectize. It is an hybrid between a text box and a select. Features include:

Search, Select, and Multi-select

Themes: Bootstrap, Select2 and Selectize

Keyboard support

This is a really awesome control let’s explore the basic usage before looking into how we can extend it.

Basic structure

See a simple example of ui-select with filtering to display a list of options.

//controller

tables = [{id:1, description:"Front"}, {id:2, description:"Back"}]; //view

<ui-select ng-model="order.table">

<ui-select-match placeholder="Select table or add new one...">

<span>{{$select.selected.description || $select.search}}</span>

</ui-select-match>

<ui-select-choices repeat="table in (tables | filter: { description: $select.search }) track by table.id">

<span>{{table.description}}</span>

</ui-select-choices>

</ui-select>

You can find ui-select dependencies and set up instructions here. Let’s review the basic structure:

ui-select , top directive to use with ng-model. On selection ng-model will take the full object selected ($select.selected).

, top directive to use with ng-model. On selection ng-model will take the full object selected ($select.selected). ui-select-match , child directive to display either the search ($select.search, user input) or the selected option object ($select.selected, user selection).

, child directive to display either the search ($select.search, user input) or the selected option object ($select.selected, user selection). ui-select-choices, child directive to display the list of options. We manually apply an object filter using filter and $select.search.

🐒 Performance tip: use track by to improve the performance of ng-repeat.

Adding new options dynamically

This is not currently supported by ui-select. Let’s see how we can add this feature.

We are going to use the refresh attribute in ui-select-choices directive to update the underlying list with the user input ($select.search).

<ui-select-choices ...

refresh=”main.refreshResults($select)”

refresh-delay=”0"

>

<span>{{table.description}}</span>

</ui-select-choices>

$select stands for the corresponding ui-select instance.

function refreshResults($select){

var search = $select.search,

list = angular.copy($select.items),

FLAG = -1; //remove last user input

list = list.filter(function(item) {

return item.id !== FLAG;

});



if (!search) {

//use the predefined list

$select.items = list;

}

else {

//manually add user input and set selection

var userInputItem = {

id: FLAG,

description: search

};

$select.items = [userInputItem].concat(list);

$select.selected = userInputItem;

}

}

We are going to set the id with a FLAG value to differentiate the user input from the regular id from the predefined list. You can use any other value.

The code above checks if we have any user input ($select.search). If there’s none, it uses the predefined list; otherwise, it adds the new option and sets the selected object to point to this new option.

Adding a custom search clear button

ui-select has a clear button option but we need to use our own as we need some extra code. This will allow the user to clear the current selection with only a click.

<ui-select-match placeholder=”Enter table…”>

<span>{{$select.selected.description || $select.search}}</span>

<a class=”btn btn-xs btn-link pull-right” ng-click=”main.clear($event, $select)”><i class=”glyphicon glyphicon-remove”></i></a>

</ui-select-match>

On the controller:

function clear($event, $select){

//stops click event bubbling

$event.stopPropagation();

//to allow empty field, in order to force a selection remove the following line

$select.selected = undefined;

//reset search query

$select.search = undefined;

//focus and open dropdown

$select.activate();

}

That’s all the code that you need to get the job done.

Let me know at @gerardsans if you know how to integrate this into ui-select or know any other solution.

Resources

angular-ui/ui-select (GitHub), AngularUI (website)