/ angularjs

Multiselect dropdowns with Angular Formly and UI-Select

In this article we'll be making multiselect dropdowns with Angular Formly and UI-Select, working with Formly is both pain as well as rewarding trust me on this one, I've used formly enough to make this comment: Formly is shit! (to implement) but its really good once you get the hang of it.

There are a few things about formly that I absolutely hate is that for every other type of field we require a plugin installed, even for smallest of things, this might be formly's way of modularizing the plugins but it surely creates a mess when it comes to managing those plugin dependencies.

Anyways we are not here to talk about the pros and cons of formly we're here to integrate multiselect dropdowns using ui-select and Angular Formly. In this example we'll create a common reusable Formly method that can be used with different types of data sets.

We need:

Lets include the relevant files:

<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.min.css">

// scripts

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-sanitize.js"></script>

// formly
<script src="//npmcdn.com/[email protected]/dist/api-check.js"></script>
<script src="//npmcdn.com/[email protected]/dist/formly.js"></script>
<script src="//npmcdn.com/[email protected]/dist/angular-formly-templates-bootstrap.js"></script>
// ui-select
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.min.js"></script>

Next we'll need to inject the dependencies in the the module and create a custom template for the dropdown which we will build upon.

    angular.module('formlyExample', ['ngSanitize', 'formly', 'formlyBootstrap', 'ui.select'], function config(formlyConfigProvider) {
  formlyConfigProvider.setType({
        name: 'ui-select-multiple',
        extends: 'select',
        templateUrl: 'ui-select-multiple.html'
    });
});     

// custom template ui-select-multiple.html

<ui-select multiple data-ng-model="model[options.key]" ng-required="{{to.required}}">
<ui-select-match placeholder="{{ to.placeholder }}">{{$item[to.labelProp]}}</ui-select-match>
<ui-select-choices data-repeat="{{ to.ngOptions }}">
    <div ng-bind-html="option[to.labelProp] | highlight: $select.search"></div>
</ui-select-choices>

A most common gotcha with Angular Formy select fields is that by default it requires your data to be in a certain format like this:

    {
     value: "News", 
     name: "News"
    }
    // notice the keys, value and name

This is the default behaviour, but luckily enough we don't have to change our backend to serve that, we can tell formly our custom field name so it can understand our data, something like this:

    {
     value: "Some data",
     key: "Some data"
       }


       var field = {
            //...
            templateOptions: {
                //..
                valueProp: "value",
                labelProp: "key",
                //..                }
        }
        // customized way of displaying the data

Lets configure the controller to make this work:

    // this is a custom method that returns a ui-select dropdown for given set of data notice the various parameters that it take so it can be customized based on the type of data

    var multiSelectDropDown = function (key, label, data, valueProp, labelProp, required) {
    return [
        {
            key: key,
            type: 'ui-select-multiple',
            templateOptions: {
                optionsAttr: 'bs-options',
                ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search',
                valueProp: valueProp,
                labelProp: labelProp,
                label: label,
                placeholder: label,
                options: data,
                required: required
            }
        }
    ];
};


// usage 

$scope.multiRegion = multiSelectDropDown("region", "Region", $scope.constants.regions, "key", "value", false);

// I believe its pretty clear as to what is happening here, "$scope.constants.regions" is the data for that dropdown, refer to jsbin demo below

This here looks very simple and infact it is, you can now generate as many dropdowns you want with this simple method and without having to repeat any of the html or any other hazard involved with it, the only thing I feel with this is that, we need to use too many plugins to make a thing, simple as this to work but other than that this is really a life saver.

Checkout the demo:

See the Pen Angular Formly Multiselect Dropdowns by Naveen Singh (@official_naveen) on CodePen.

Hope this helps, happy coding!

Naveen Singh

Naveen Singh

I am Full Stack Developer from India who loves design, I use Python and Javascript to curb my cravings, with additional dosages of various web and mobile frameworks.

Read More