Установите вложенные формы 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. Однако только у родительской формы для флага $submitted установлено значение true, что проблематично, поскольку я использую его для запуска отображения определенных сообщений об ошибках. Я не хочу, чтобы дочерняя форма проверяла, отправлена ​​ли родительская форма, поскольку это два отдельных файла. Единственный вариант, который мне пришел в голову, - это вызов метода submit() $setSubmitted() в дочерней форме, что неудобно, поскольку теперь родительская форма должна напрямую ссылаться на дочернюю форму. Есть ли лучший способ установить $submitted дочерней формы в true?


person sslepian    schedule 13.09.2014    source источник
comment
как это: вызвать отображение определенных сообщений об ошибках?   -  person André Werlang    schedule 13.03.2015


Ответы (4)


В качестве расширения решения Микера вы можете неявно достичь $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();
      }); 
    }
  };
})
person scarlz    schedule 09.05.2015
comment
Обратите внимание, что это работает, только если formCtrl.$submitted изменено. Так что это может не работать с динамическим вложенным ng-form. - person stevemao; 21.12.2015

В системе отслеживания ошибок 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);
    }
}
person Jonathan    schedule 25.01.2016

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

Я сделал директиву 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');
}
person Meeker    schedule 30.09.2014

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

Вместо того, чтобы использовать ng-show и иметь дело с возможными существующими данными, я изменил решение Scarlz, чтобы использовать событие отправки вместо просмотра свойства 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);

person severin    schedule 16.05.2017