Skip nested forms validation with AngularJS

后端 未结 12 1998
失恋的感觉
失恋的感觉 2020-12-23 18:16

How can I skip validation of nested forms with AngularJS? I have to make an outer form valid even when its child form is invalid.

In the example below outer form sh

相关标签:
12条回答
  • 2020-12-23 18:28

    At least with Angular 1.5 it seems to be enough to remove the nested form from the parent using $removeControl:

    module.directive('isolateForm', function() {
      return {
        restrict: 'A',
        require: '?form',
        link: function(scope, element, attrs, formController) {
          if (!formController) {
            return;
          }
    
          var parentForm = formController.$$parentForm; // Note this uses private API
          if (!parentForm) {
            return;
          }
    
          // Remove this form from parent controller
          parentForm.$removeControl(formController);
        }
      };
    });
    

    Et voila, pristine and validity states of the parent are no longer affected by the nested form.

    0 讨论(0)
  • 2020-12-23 18:31

    i'd like to suggest mbernath's version without downside

    angular.module('yourModule').directive('isolatedForm', [function () {
    return {
        restrict: 'A',
        require: '?form',
        link: function link(scope, element, iAttrs, formController) {
    
            if (!formController) return;
    
            // Remove this form from parent controller
            var parentFormController = element.parent().controller('form');
            parentFormController.$removeControl(formController);
            // override default behavior
            var _handler = formController.$setValidity;
            formController.$setValidity = function (validationErrorKey, isValid, cntrl) {
                _handler(validationErrorKey, isValid, cntrl);
                parentFormController.$setValidity(validationErrorKey, true, this);
            }
        }
    };}]);
    
    0 讨论(0)
  • 2020-12-23 18:35

    I had the same issue and resolve it with bit change in local copy of angular.js file itself.

    Basically, I added new function to the FormController as below:

    form.$resetParent = function() {
        parentForm = nullFormCtrl;
    };
    

    and create custom directive:

    angular.module('myApp').directive('dtIsolatedForm', function () {
        return {
            restrict: 'A',
            require: '?form',
            link: function (scope, element, attrs, formController) {
                if (!formController || !formController.$parentForm) {
                    return;
                }
    
                formController.$resetParent();
            }
        };
    });
    
    0 讨论(0)
  • 2020-12-23 18:38

    I found out the solution that worked best was Anton's.

    Setting the nullFormCtrl suggested by mbernath disables validation on the child form (thxs for paving the way though...).

    The only change that I made was in the way the parentForm is accessed. angular does provide a method for that.

    .directive('isolateForm', [function () {
        return {
            restrict: 'A',
            require: '?form',
            link: function link(scope, element, iAttrs, formController) {
    
                if (!formController) {
                    return;
                }
    
                // Remove this form from parent controller
                formController.$$parentForm.$removeControl(formController)
    
                var _handler = formController.$setValidity;
                formController.$setValidity = function (validationErrorKey, isValid, cntrl) {
                    _handler(validationErrorKey, isValid, cntrl);
                    formController.$$parentForm.$setValidity(validationErrorKey, true, this);
                }
            }
        };
    }]);

    0 讨论(0)
  • 2020-12-23 18:40

    Before you check if the form is valid, simply remove the nestled forms! vm.parentForm.$removeControl(vm.nestledForm);

    0 讨论(0)
  • 2020-12-23 18:44

    Here is my solution inspired by mbernath, that isolates completely the form itself from its father.

    This solution take care of the:

    • Form validity ($valid, $invalid)
    • Form interaction ($pristine, $dirty)
    • Nested forms validity and interaction

    See it in action in this JSFiddle.

    angular.module('isolateForm',[]).directive('isolateForm', [function () {
        return {
            restrict: 'A',
            require: '?form',
            link: function (scope, elm, attrs, ctrl) {
                if (!ctrl) {
                    return;
                }
    
                // Do a copy of the controller
                var ctrlCopy = {};
                angular.copy(ctrl, ctrlCopy);
    
                // Get the parent of the form
                var parent = elm.parent().controller('form');
                // Remove parent link to the controller
                parent.$removeControl(ctrl);
    
                // Replace form controller with a "isolated form"
                var isolatedFormCtrl = {
                    $setValidity: function (validationToken, isValid, control) {
                        ctrlCopy.$setValidity(validationToken, isValid, control);
                        parent.$setValidity(validationToken, true, ctrl);
                    },
                    $setDirty: function () {
                        elm.removeClass('ng-pristine').addClass('ng-dirty');
                        ctrl.$dirty = true;
                        ctrl.$pristine = false;
                    },
                };
                angular.extend(ctrl, isolatedFormCtrl);
            }
        };
    }]);
    

    To use it just call the directive "isolate-form" :

    <form name="parent">
        <input type="text" ng-model="outside"/>
        <ng-form name="subform" isolate-form>
            <input type="text" ng-model="inside"/>
        </ng-form>
    </form>
    
    0 讨论(0)
提交回复
热议问题