Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS ng-options custom attribute

I currently have the following directive on my select.

ng-options="option.value as option.title for option in exportTypes"

$scope.exportTypes = an array of objects each with title, value, and generatesFile attributes. I'd like the generatesFile attribute to be added as a data-generates-file attribute on each <option> that is generated for this select.

Any thoughts on how to do this?

like image 393
Ilan Biala Avatar asked Jan 11 '23 05:01

Ilan Biala


2 Answers

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.

like image 77
Chev Avatar answered Jan 17 '23 16:01

Chev


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

like image 38
vtor Avatar answered Jan 17 '23 16:01

vtor