tarekahf tarekahf - 1 month ago 7
AngularJS Question

Enable/disable validation for angular form with nested sub-forms using `ng-form`

I need to enable/disable all validation rules in Angular form or subform under

ng-form="myForm"
based on a scope variable
$scope.isValidationRequired
. So, if
isValidationRequired
is
false
, none of the validations set for the designated group of fields will run, and the result will always be
myForm.$valid==true
, otherwise, the validation rules will run as usual.

I did a lot of research, and realized that this feature is not available out of the box with Angular. However, I found some add-ons or with some customization, it is possible.

For example, I can use the add-on angular-conditional-validation (github and demo) with custom directive
enable-validation="isValidationRequired"
. This will be perfect, except that I cannot apply this feature for a group of fields under
ng-form
. I have to add this directive for each and every field where applicable.

The other solution is to use custom validation using Angular
$validators
pipeline. This requires some extra effort and I don't have time since the sprint is almost over and I have to give some results in a few days.

If you have any other suggestions please post an answer.

Use Case:



To clarify the need for this, I will mention the use-case. The end user can fill the form with invalid data and he can click
Save
button and in this case, the validation rules shouldn't be triggered. Only when the user clicks
Validate and Save
then the validation rules should be fired.

Solution:



See the final plunker code here.

UPDATE: as per comments below, the solution will cause the browser to hang if inner subforms are used under
ng-form
. More effort is needed to debug and resolver this issuer. If only one level is used, then it works fine.

UPDATE: The plunker here was updated with a more general solution. Now the code will work with a form that has sub-forms under
ng-form
. The function
setAllInputsDirty()
checks if the object is a
$$parentForm
to stop recursion. Also, the
changeValidity()
will check if the object is a form using
$addControl
then it will call itself to validate its child objects. So far, this function works fine, but it needs a bit of additional optimization.

Answer

One idea is to reset the errors in the digest loop if the validation flag is disabled. You can iterate through the form errors on change and set them to valid, one by one.

$scope.$watch(function() {
    $scope.changeValidity();
}, true);

$scope.changeValidity = function() {
    if ($scope.isValidationRequired === "false") {
        for (var error in $scope.form.$error) {
            while ($scope.form.$error[error]) {
                $scope.form.$error[error][0].$setValidity(error, true);
            }
        }
    }
}

Here is a plunkr: https://plnkr.co/edit/fH4vGVPa1MwljPFknYHZ