AngularJS ng-options custom attribute AngularJS ng-options custom attribute angularjs angularjs

AngularJS ng-options custom attribute


Maybe someone will correct me but I'm pretty sure you won't get this kind of control out of ng-options. Angular manages the select behind the scenes for you when you use this, which is nice 90% of the time but can be limiting in situations like yours. I'm not sure what benchmarks you're looking at but I'd be willing to bet an ng-repeat on the option elements is comparable in performance to using ng-options.

I'd go with something like this:

<select ng-model="selectedExportType">    <option ng-repeat="exportType in exportTypes" data-generates-file="{{exportType.generatesFile}}" value="{{exportType.value}}">        {{exportType.title}}    </option></select>

Edit:

Of course, this assumes you really do need that attribute on there. If all you need is access to that attribute on select then this is where ng-options shines. Simply remove the option.value as bit from your select and then you get the whole object back from your array when you make a selection.

http://plnkr.co/edit/6XPaficTbbzozSQqo6uE?p=preview

You can see in that demo that the selected item is the whole object, complete with someAttr property which was never used in the select at all. If you inspect the DOM you won't see it. Angular tracks all this behind the scenes.


Here is a directive which can be used to add custom attributes when using ng-options with <select>, so you can prevent using ng-repeat

.directive('optionsCustomAttr', function ($parse) {        return {            priority: 0,            require: 'ngModel',            link: function (scope, iElement, iAttrs) {                scope.addCustomAttr = function (attr, element, data, fnDisableIfTrue) {                    $("option", element).each(function (i, e) {                        var locals = {};                        locals[attr] = data[i];                        $(e).attr(iAttrs.customAttrName ? iAttrs.customAttrName : 'custom-attr', fnDisableIfTrue(scope, locals));                    });                };                var expElements = iAttrs['optionsCustomAttr'].match(/(.+)\s+for\s+(.+)\s+in\s+(.+)/);                var attrToWatch = expElements[3];                var fnDisableIfTrue = $parse(expElements[1]);                scope.$watch(attrToWatch, function (newValue) {                    if (newValue)                        scope.addCustomAttr(expElements[2], iElement, newValue, fnDisableIfTrue);                });            }        };     })

And then in your select,

<select ng-model="selectedExportType" ng-options="option.value as option.title for option in exportTypes"                   options-custom-attr="option.generatesFile for option in exportTypes"                   custom-attr-name="data-generates-file"></select>

Note: This is a modified version of optionsDisabled directory mentioned here


Or a simpler solution:

<select ng-model="selectedItem" ng-options="item as item.name for item in items" option-style="items"></select>

And the directive which inserts whatever you want in each option tag.

angular.directive('optionStyle', function ($compile, $parse) {    return {        restrict: 'A',        priority: 10000,        link: function optionStylePostLink(scope, elem, attrs) {            var allItems = scope[attrs.optionStyle];            var options = elem.find("option");            for (var i = 0; i < options.length; i++) {                angular.element(options[i]).css("color", allItems[i].yourWantedValue);            }        }    };});