Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS custom directive for a ng-indeterminate attribute on checkboxes

Here is a directive that handles the indeterminate state on checkboxes:

.directive('ngIndeterminate', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attributes) {
            attributes.$observe('ngIndeterminate', function(value) {
                $(element).prop('indeterminate', value == "true");
            });
        }
    };
})

Then, for example with these data:

$scope.data = [
    {name: 'foo', displayed: 2, total: 4},
    {name: 'bar', displayed: 3, total: 3}
];

You would simply need:

<ul ng-repeat="item in data">
    <li>
        <input type="checkbox" ng-indeterminate="{{item.displayed > 0 && item.displayed < item.total}}" ng-checked="item.displayed > 0" />
        {{item.name}} ({{item.displayed}}/{{item.total}})
    </li>
</ul>

Is there any way to write the ng-indeterminate expression without the double-curly notation, just as the native ng-checked one?

ng-indeterminate="item.displayed > 0 && item.displayed < item.total"

I tried:

.directive('ngIndeterminate', function($compile) {
    return {
        restrict: 'A',
        link: function(scope, element, attributes) {
            attributes.$observe('ngIndeterminate', function(value) {
                $(element).prop('indeterminate', $compile(value)(scope));
            });
        }
    };
})

But I get the following error:

Looking up elements via selectors is not supported by jqLite!

Here is a fiddle you can play with.

like image 616
sp00m Avatar asked Mar 03 '14 09:03

sp00m


1 Answers

First off, you do not need to wrap element in jQuery if you load jQuery before angular. So you would then never need to use $(element) inside your directives and instead can use element directly as angular will automatically wrap element as a jQuery object.

For your example, you don't actually even need jQuery, so the answer provided below does not rely on jQuery at all.

As to your question, you can $watch your attribute values, angular automatically returns the compiled attribute value. So the following works as you would expect:

.directive('ngIndeterminate', function($compile) {
    return {
        restrict: 'A',
        link: function(scope, element, attributes) {
            scope.$watch(attributes['ngIndeterminate'], function (value) {
                element.prop('indeterminate', !!value);
            });
        }
    };
});

Here's a working jsfiddle: http://jsfiddle.net/d9rG7/5/

like image 150
Beyers Avatar answered Sep 22 '22 08:09

Beyers