Set AngularJS nested forms to submitted

梦想的初衷 提交于 2019-12-01 04:18:47

As an extension of Meeker's solution, you could achieve the $broadcast implicitly by adding a watch to the parent form:

.directive('form', function() {
  return {
    restrict: 'E',
    require:  'form',
    link: function(scope, elem, attrs, formCtrl) {

      scope.$watch(function() {
        return formCtrl.$submitted;
      }, function(submitted) {
        submitted && scope.$broadcast('$submitted');
      });
    }
  };
})

.directive('ngForm', function() {
  return {
    restrict: 'EA',
    require:  'form',
    link: function(scope, elem, attrs, formCtrl) {

      scope.$on('$submitted', function() {
        formCtrl.$setSubmitted();
      }); 
    }
  };
})

There's an issue in angular's bug tracker for this https://github.com/angular/angular.js/issues/10071. One comment suggests this workaround in the meantime:

// sets all children ng-forms submitted (no such default functionality)
function setSubmitted(form) {
    form.$setSubmitted();
    angular.forEach(form, function(item) {
        if(item && item.$$parentForm === form && item.$setSubmitted) {
            setSubmitted(item);
        }
    });
}

// so ie. instead of scope.form.$setSubmitted(); use:    
setSubmitted(scope.form);

One problem with this approach is that any forms added dynamically will not copy their parent's initial state. I'm using this when adding forms dynamically:

function onNewChildForm (form) {
    if(form.$$parentForm && form.$$parentForm.$submitted) {
        setFormSubmitted(form);
    }
}

This was my solution to this problem (and I bet someone can make this prettier)

I made an ngForm directive that attached a listener,

.directive('ngForm', function(){
    return {
        restrict: 'AE',
        require: 'form',
        link: function(scope,element,attrs,form){
            var parentForm = element.parent().controller('form');
            if(parentForm){
                scope.$on('parentFormSubmitted',function(event){
                    form.$setSubmitted();
                });
            }
        }
    };
})

Then in the controller of the parent form I execute this peice of code when the form is submitted

$scope.submit = function(){
  $scope.$broadcast('parentFormSubmitted');
}

I initially used Scarlz' solution, but in my situation I had several nested ng-forms that are created/destroyed by ng-if.

Rather than using ng-show and dealing with possibly existing data, I modified Scarlz' solution to use the submit event instead of watching the form.$submittedproperty

  function ParentFormThatSubmits() {
    return {
      restrict: 'E',
      require: 'form',
      link: function(scope, elem, attrs, formCtrl) {
        elem.on('submit', function() {
          var submitted = formCtrl.$submitted;
          if(submitted) {
            scope.$broadcast('$submitted');
          }
        });
      }
    };
  }

  function ChildFormThatSubmits() {
    return {
      restrict: 'EA',
      require: 'form',
      link: function(scope, elem, attrs, formCtrl) {
        scope.$on('$submitted', function() {
          formCtrl.$setSubmitted();
          scope.$apply();
        });
      }
    };
  }

  angular.module('appModule')
    .directive('form', ParentFormThatSubmits)
    .directive('ngForm', ChildFormThatSubmits);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!