Customize ng-options selection look

ncohen picture ncohen · Jul 8, 2014 · Viewed 23.7k times · Source

I'm using a ng-options for a select dropdown menu. I would like to use different color for an option depending on a condition:

select(ng-model='myCompany', ng-options='company.code as company.name for company in companies' **if company.active -> text-color=green**)

Is it possible to do that?

Edit (my jade code):

 form(role='form', name='addForm', novalidate, rc-submit="add()")
    .form-group
        div.row
            div.col-xs-12.col-md-3
                select.form-control(ng-model='form.contract', ng-options='contract as contract.number for contract in contracts', options-class="{true:'active',false:'inactive'}[active]")

Answer

gkalpak picture gkalpak · Jul 8, 2014

If you only need to bind the select to string values (not object), you can easily achieve what you want by using ngRepeated <option> elements (instead of ngOptions):

<select ng-model="color">
    <option value="">--- Select a color ---</option>
    <option value="{{c}}" style="background-color:{{c}}" ng-repeat="c in colors">
        {{c}}
    </option>
</select>

If you are in for a little custom directive, you can implement it like this:

app.directive('optionClassExpr', function ($compile, $parse) {
    var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;

    return {
        restrict: 'A',
        link: function optionClassExprPostLink(scope, elem, attrs) {
            var optionsExp = attrs.ngOptions;
            if (!optionsExp) return;

            var match = optionsExp.match(NG_OPTIONS_REGEXP);
            if (!match) return;

            var values = match[7];
            var classExpr = $parse(attrs.optionClassExpr);

            scope.$watchCollection(function () {
                return elem.children();
            }, function (newValue) {
                angular.forEach(newValue, function (child) {
                    var child = angular.element(child);
                    var val   = child.val();
                    if (val) {
                        child.attr('ng-class', values + '[' + val + '].' +
                                               attrs.optionClassExpr);
                        $compile(child)(scope);
                    }
                });
            });
        }
    };
});

And use it like this:

<select ng-model="someObj" ng-options="obj as obj.color for obj in objects"
        option-class-expr="color">
</select>

See, also, this updated short demo.