How to let ng-disabled directive work with isolated scope

19,181

Solution 1

I had this same issue, and the easiest solution imho. is to use the isolated scope to inherit the property of ngDisabled.

angular.module('directives', [])
.directive('conditionalAutofocus', function () {
    return {
        restrict:'A',
        scope:{
            condition:'&conditionalAutofocus',
            disabled:'=ngDisabled'
        },
        link:function (scope, element, attrs) {
            if (scope.condition()) {
                attrs.$set('autofocus','true');
            }
            if(scope.disabled){
                //is disabled
            }
        }
    }
});

Might only work for restrict : 'E'. Have not tested others

Solution 2

I had a similar problem lately. I wanted to disable a button in isolated scope and use this nice angular ng-disabled directive. After some digging I came to a solution like this:

link: function($scope, element, attrs){

    $scope.$parent.$watch(attrs.ngDisabled, function(newVal){
        element.prop('disabled', newVal);
    });

    //...
}

To evaluate the ng-diabled expression instead of $scope just jump to $scope.$parent and all your variables will be avaliable. Unfortunatly manually setting the disabled property is required.

Solution 3

OK, for my own case above my solution is to change the implementation of directive, not use isolated scope anymore:

angular.module('directives', [])
.directive('conditionalAutofocus', function () {
    return {
        restrict:'A',
        link:function (scope, element, attrs) {
            scope.$watch(attrs.conditionalAutofocus, function(){
                if (scope.$eval(attrs.conditionalAutofocus)) {
                    element.focus();
                }else{
                    element.blur();
                }
            });
        }
    }
});

Solution 4

You can set up a bi-directional binding to the parent scope in your isolated scope definition. Then add a watch on the isolated scope property. This just duplicates the code in the ngReadonly directive.

angular.module('directives', [])
.directive('conditionalAutofocus', function () {
    return {
        restrict:'A',
        scope:{
            condition: '&conditionalAutofocus',
            isReadonly: '=ngReadonly'
        },
        link:function (scope, element, attrs) {
            if (scope.condition()) {
                attrs.$set('autofocus','true');
            }

            scope.$watch('isReadonly', (value) => {
                attrs.$set('readonly', !!value);
            });
        }
    }
});
Share:
19,181

Related videos on Youtube

yi mo
Author by

yi mo

Updated on September 15, 2022

Comments

  • yi mo
    yi mo over 1 year

    Recently I have to make a Input element work with both ng-disabled and an custom directive which use isolated scope to evaluate expression just like what ng-disabled is doing, somehow, the custom directive works fine but ng-disabled doesn't, since it only evaluate expression within the isolated scope.

    The custom directive is quite simple like:

    angular
      .module('directives', [])
      .directive('conditionalAutofocus', function () {
        return {
            restrict:'A',
            scope:{
                condition:'&conditionalAutofocus'
            },
            link:function (scope, element, attrs) {
                if (scope.condition()) {
                    attrs.$set('autofocus','true');
                }
            }
        }
    });
    

    while the page looks like:

    <input name="pin"
           ng-model="pin"
           type="password"
           required
           ng-disabled="names == null"
           conditional-autofocus="names != null" />
    

    Anybody already has solution for this issue?

    Thanks in advance! Yanni