Установить 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);