13

My directive has

link: function ($scope, $elm, $attrs) {
    var status = $scope.item.status
    if (status) {
        var statusName = status.name,
            item = $scope.item;
        if (statusName === 'USED') {
            $attrs.$set('ng-disabled', true); // this doesn't work
        } else {
            $elm.attr('ng-disabled', false);
        }
    }
}

So, my question is:

How to apply ng-disabled to element with this directive?

uladzimir
  • 5,639
  • 6
  • 31
  • 50

3 Answers3

15
if (statusName === 'USED') {
    $attrs.$set('disabled', 'disabled');
} else {
    $elm.removeAttr('disabled');
}

Why invoke ng-disable at all? You're already once evaluating the condition yourself, so having ng-disable evaluating it again is redundant.

laggingreflex
  • 32,948
  • 35
  • 141
  • 196
  • thanks for your answer. I don't remember, why I used "ng-disabled" instead of "disabled" :) – uladzimir Sep 15 '14 at 12:51
  • According to the docs -- The HTML specification does not require browsers to preserve the values of boolean attributes such as disabled. (Their presence means true and their absence means false.) If we put an Angular interpolation expression into such an attribute then the binding information would be lost when the browser removes the attribute. The ngDisabled directive solves this problem for the disabled attribute. This complementary directive is not removed by the browser and so provides a permanent reliable place to store the binding information. – Craig Nov 25 '14 at 15:10
  • @Craig Appreciate the correction, but I still fail to see why it would be better to use ng-disabled in *this particular case*. Could you explain? I'm essentially *removing* and *adding* the disabled attribute, so it shouldn't matter whether browser discards it's value, should it? – laggingreflex Nov 25 '14 at 17:40
  • You want to try to avoid manipulating the DOM when using Angular. – Thierry J. Jun 06 '16 at 01:00
  • 1
    @Thierry J. Why that? Angular is absolutely fine for modifying the DOM. But do it with directives. – Fortuna Oct 31 '16 at 13:13
  • Yes, it is, but in this case you have a solution that completely avoids manipulating the DOM, which is IMHO more "angulary" – Thierry J. Nov 01 '16 at 21:27
  • This is a better answer as it addresses the "inside of a directive" portion of the question. The accepted answer doesn't, that's an approach for a controller. – Kevinleary.net Sep 11 '17 at 18:53
13

You would set ng-disabled to a scope variable, ex:

<input ng-disabled="isDisabled" />

And then inside your directive you can set that variable:

$scope.isDisabled = true;
tymeJV
  • 103,943
  • 14
  • 161
  • 157
4
//html
<div ng-app="miniapp" ng-controller="MainCtrl">
    <input type="submit" mydir>
</div>
//js
'use strict';
            var app = angular.module('miniapp', []);
            app.directive('mydir', function ($compile) {
                return {
                    priority:1001, // compiles first
                    terminal:true, // prevent lower priority directives to compile after it
                    compile: function(el) {
                        el.removeAttr('mydir'); // necessary to avoid infinite compile loop
                        return function(scope){
                            var status = scope.item.status
                            if (status === 'USED') {
                                el.attr('ng-disabled',true);
                            } else {
                                el.attr('ng-disabled',false);
                            }
                            var fn = $compile(el);
                            fn(scope);
                        };
                    }


                };
            });
            app.controller('MainCtrl', function ($scope) {
                $scope.item = {};
                $scope.item.status = 'USED';
            });

credit to Ilan Frumer

Community
  • 1
  • 1
Whisher
  • 31,320
  • 32
  • 120
  • 201