Please check this code sample here:
http://plnkr.co/edit/zQ049VsfrprutNYkZm3y?p=preview
This code sample uses the directive check-if-required
to add ng-required
attribute. When page loading is completed, the input element with test_me
is set as required.
Now suppose at some point later, the list of required fields has changed, how is it possible to re-run that directive in order to change the ng-required
attribute of the new fields that have become required.
Tarek.
UPDATE 2:
After a lot of research and trials, I realized that this request is not practical and should not be approached. The problem I was trying to solve is slow loading of HTML in IE11 due to adding validation rules during runtime.
See related post here in attempt to solve the problem.
Also, check the final work here.
I was trying to modify the HTML attributes/directives to add validation such as ng-reuqired
and then use $compile
as this is required by AngularJS to have dynamic validation.
After reading the solutions and comments added here, I think there is a better option.
Instead of modifying the element HTML by adding 'ng-required' directive, then compile, instead, I can skip HTML and use the ngModel.NgModelController
of the related HTML Element, then access the $validators
to perform validation using code. If you read the code here, you will see that I have already accessed the ngModel.NgModelController
for each element in variable elmModel
. I think this variable will provide access to $validators
which can be used to add validation to the element. Since the rules are now available in validationList
variable, I will write a function to perform validation by looking up this list and apply the available validation on-the-fly.
This will be the improvement in the future sprints.
If you need such solution you may keep and eye on this post as I am planning to implement the newly proposed approach.
This post can be closed for now.
Tarek
UPDATE1:
As I am replying to the comments, the solution flashed in my head... so thank you all for forcing me to think to get the solution.
Simply, I will create a scope function isFieldRequired()
inside the directive check-if-required
. This function will accept the element ID and if the element ID is found it the list of required fields listRequiredFields
, it will return true, and false otherwise. At this point in time, I have access to the element ID so there is no problem here. Eventually, the HTML will look something like the following:
<input id="some_id" type="text" ng-required="isFieldRequired('some_id')">
Finally, the $compile
service will be executed over the modified HTML element.
Below is the high-level structure of the directive check-if-required
:
app.directive('checkIfRequired', ['$compile', '$timeout', '$interpolate', function ($compile, $timeout, $interpolate) {
return {
//JIRA: NE-2682 - trying to solve issue of interference between datepicker popup box and `$compile` service.
priority: 100,
terminal: true,
require: '?^form',
link: function (scope, el, attrs, ngForm) {
scope.isFieldRequired = function (prmFieldName) {
var isFound;
isFound = scope.listRequiredFields.indexOf(prmFieldName) !== -1;
return isFound;
}
var children;
//Use timeout to give chance for inner block elements to finish rendering
$timeout(function() {
children = $(":input", el);
angular.forEach(children, function(child, key) {
var childID = (child?child.id:"") || "";
if (childID.indexOf("{{") >= 0) {
childID = $interpolate(childID)(scope);
}
if(child && childID) {
angular.element(child).attr("ng-required", "isFieldRequired('" + childID + "')");
}
});
$compile(el, null, 100)(scope);
}, 100)
}
};
}]);
To use check-if-required
add it to any parent element as follows:
<div ng-form="masterForm" check-if-required>
<label>First Name:</label><input id="firsName" type="text"><br>
<label>Last Name:</label><input id="lastName" type="text"><br>
<label>Age:</label><input id="age" type="number"><br>
<label>Address:</label><input id="address" type="text"><br>
</div>
When I implement the above successfully, I will add it as a solution.
The only drawback of the above solution is that the ng-required
directive will be added for all fields even if not relevant. That is why I was searching for a way to re-apply the directive check-if-required
.
Tarek