Угловой ng-повтор с ng-формой, доступ к проверке в контроллере
-
21-12-2019 - |
Вопрос
Я пытаюсь сгенерировать редактируемый список, используя ng-repeat
.Я хочу напомнить пользователю обновить все правки, прежде чем двигаться дальше, поэтому я использую ng-form
создавать "вложенные" формы "на лету", потому что в документации сказано, что затем я могу использовать проверку для этих динамически создаваемых входных данных.
Хотя это, кажется, работает в HTML, я не вижу, как получить доступ к этим динамически создаваемым формам и связанным с ними полям проверки в контроллере.В частности, когда пользователь изменяет входные данные, я использую свойство form $dirty, чтобы вызвать кнопку, указывающую пользователю зафиксировать изменения.Пока все идет так хорошо.Однако, как только изменения будут внесены, я хочу $setPristine()
в поле, указывающем на то, что изменения были внесены.Могут быть и другие способы гарантировать, что изменения будут зафиксированы при каждом вводе до того, как я разрешу зафиксировать основную форму, но это было лучшее, что я смог придумать.
К сожалению, даже несмотря на то, что в документации сказано, что если я назову ng-форму, она будет распространена на $scope
объект, я не могу найти способ получить к нему доступ. $scope.dynamic_form
не определено.
Вот планка, показывающая, что я имею в виду:
Спасибо!
[РЕДАКТИРОВАТЬ] Просто чтобы добавить к проблеме, что действительно работает для этого конкретного примера, так это добавить к ng-click
на динамически создаваемых входных данных:
ng-click="namesForm.name.$setPristine();clean()"
Но у меня по-прежнему нет доступа к динамически создаваемой форме в контроллере.Я хотел бы, например, добавить наблюдателя в namesForm.name.$pristine
чтобы я мог установить mainForm.$setValidity(false)
всякий раз, когда подформа является $dirty
запретить пользователю отправлять основную форму до тех пор, пока не будут зафиксированы все изменения во вложенной форме.
Итак, в двух словах, проблема заключается в том, как получить доступ в родительском контроллере к значениям проверки динамически создаваемой вложенной ngForm?
Решение
Обновлено 2015-01-17:
Как указал Леблан Менесес в комментариях Угловой 1.3 теперь поддерживается интерполяция с помощью form
, ngForm
и input
директивы.
Это означает, что использование выражений для присвоения имен вашим элементам:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<input type="text"
name="input_{{$index}}_0"></input>
<!-- ... -->
</div>
будет работать так, как ожидалось:
$scope['namesForm_0']
$scope.namesForm_1
// Access nested form elements:
$scope.namesForm_1.input_1_0
...
Оригинальный ответ для Angular <= 1.2:
Работа с формами и ngFormController
может довольно быстро стать сложным.
Вы должны знать, что вы можете динамически добавлять элементы формы и входные данные, но они не могут быть динамически названный - интерполяция не работает в ngForm
или name
директивы.
Например, если вы попытались динамически называть свои вложенные формы следующим образом:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<!-- ... -->
</div>
Вместо того, чтобы делать все вложенные формы доступными в области видимости следующим образом: scope['namesForm_0']
у вас будет доступ только к единственной (последней) форме с буквальным именем scope['namesForm_{{$index}}']
.
В вашей ситуации вам нужно создать пользовательскую директиву, которая будет добавлена вместе с ngForm
для обработки настроек $pristine$
и $invalid
для этого экземпляра формы.
JavaScript:
Эта директива будет следить за $dirty
состояние его формы для установки $validity
чтобы предотвратить подачу при загрязнении и отрегулировать настройку $pristine
состояние при нажатии кнопки "очистить".
app.directive('formCleaner', function(){
return {
scope: true,
require: '^form',
link: function(scope, element, attr){
scope.clean = function () {
scope.namesForm.$setPristine();
};
scope.$watch('namesForm.$dirty', function(isDirty){
scope.namesForm.$setValidity('name', !isDirty);
});
}
};
});
HTML:
Тогда единственное изменение в вашем HTML-файле - это добавление formCleaner
директива.
Так что измените свой исходный HTML-код на этот:
<body ng-controller="MainCtrl">
<form name="mainForm" submit="submit()">
<h3>My Editable List</h3>
<div ng-form="namesForm"
ng-repeat="name in names">
<!-- ... -->
</div>
<button class="btn btn-default" type="submit">Submit</button>
</form>
</body>
к этому, добавив form-cleaner
рядом с ng-form
:
<body ng-controller="MainCtrl">
<form name="mainForm" submit="submit()">
<h3>My Editable List</h3>
<!-- Add the `form-cleaner` directive to the element with `ng-form` -->
<div form-cleaner
ng-form="namesForm"
ng-repeat="name in names">
<!-- ... -->
</div>
<button class="btn btn-default" type="submit">Submit</button>
</form>
</body>
Вот обновленный поршень, показывающий новое поведение: http://plnkr.co/edit/Lxem5HJXe0UCvslqbJr3?p=preview