What do you think about this directive? For each input
, it traverses the DOM towards the root and if it finds an element with the class readonly
, it makes the input readonly
.
An ng-readonly
directive on the input
itself get honored: The input becomes readonly whenever ng-readonly
evaluates to true or any enclosing element has the class readonly
.
.directive("input", function($parse) {
return {
restrict: "E",
link: function($scope, element, attr) {
if (attr.type === "radio" || attr.type === "checkbox") {
return; // for simplicity, let's ignore them
}
var org = attr.ngReadonly;
if (!org && attr.readonly) {
return; // readonly seems to be set manually, so let's not touch it
}
$scope.$watch(function() {
var readonly = $parse(org)($scope);
for (var e = element; e.length && !readonly; e=e.parent()) {
readonly = e.hasClass("readonly");
}
console.log(element.attr("ng-model"), readonly)
attr.$set("readonly", !!readonly);
});
},
};
})
The purpose is to allow to make a whole subtree readonly, no matter what's inside. It works, but I can imagine there can be performance problems and/or interferences with ng-readonly
setting the value independently of this directive.
An explanation why I'm not simply binding to a scope variable
While I really appreciate Thomas' answer, I disagree with this part:
Again, I highly recommend that you simply bind to a scope variable instead of checking for the presence of a class further up the tree.
I really find it both complicated and error-prone: I'm having a big form in which many fields already have their readonly
logic (e.g., bank name is read only when a known BIC is entered). Now, I'd have to add is_readonly
to all existing ng-readonly
directives and add the directive to every input
field missing it.
Moreover, the form includes some partials, which have no idea about the outer scope. Again, I'd have to add change the partial as above and make it to get is_readonly
from the outer scope.
org
is undefined \$\endgroup\$ng-include
creates a new child scope for the included fragment. Also, instead of havingng-readonly
interrogate scope variables directly, have it call a function on your scope. Then you can have arbitrarily complicated logic without encoding it in your templates. \$\endgroup\$