Установить AngularJS вложенных форм для отправки

У меня есть вложенная форма AngularJS примерно так:

<form name="parentForm" ng-submit="submit()">
    <input name="parentInput" type="text">
    <ng-include src="childForm.html" ng-form="childForm"></ng-include>
    <button type="submit">Submit</submit>
</form>

А вот и childForm.html

<input name="childInput" type="text">

По причинам, не связанным с вопросом, я не могу объединить родительскую и дочернюю формы - они должны быть двумя отдельными файлами.

Теперь, когда пользователь нажимает кнопку отправки, проверка корректно применяется как к parentForm, так и к childForm. Тем не менее, только родительская форма имеет флаг $ submit, установленный в true, что проблематично, поскольку я использую ее для запуска отображения определенных сообщений об ошибках. Я не хочу, чтобы дочерняя форма проверяла, отправлена ​​ли родительская форма $, поскольку это два отдельных файла. Единственная опция, которая пришла мне в голову - это вызвать метод submit() $setSubmitted() в дочерней форме, что неудобно, поскольку теперь родительская форма должна напрямую ссылаться на дочернюю форму. Есть ли лучший способ установить $ дочерней формы, отправленной в true?

4 ответа

В качестве расширения решения Meeker's вы могли бы достичь $broadcast неявно, добавив часы в родительскую форму:

.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();
      }); 
    }
  };
})

Есть проблема в трекере ошибок Angular для этого https://github.com/angular/angular.js/issues/10071. Один комментарий предлагает этот обходной путь в то же время:

// 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);

Одна проблема с этим подходом состоит в том, что любые формы, добавленные динамически, не будут копировать начальное состояние своего родителя. Я использую это при добавлении форм динамически:

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

Это было мое решение этой проблемы (и я уверен, что кто-то может сделать это красивее)

Я сделал директиву ngForm, которая прикрепила слушателя,

.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();
                });
            }
        }
    };
})

Затем в контроллере родительской формы я выполняю этот кусок кода при отправке формы

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

Я изначально использовал решение Scarlz, но в моей ситуации у меня было несколько вложенных ng-form s, которые созданы / уничтожены ng-if,

Вместо того, чтобы использовать ng-show Имея дело с возможными данными, я модифицировал решение Scarlz, чтобы использовать событие submit вместо просмотра form.$submitted имущество

  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);

Другие вопросы по тегам