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
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.
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();
}
});
}
}
});
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
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);
});
}
}
});