Угловой NG-повтор с NG-формы, доступ к проверке в контроллере
Я пытаюсь создать редактируемый список, используя ng-repeat
, Я хочу напомнить пользователю обновить любые изменения, прежде чем двигаться дальше, поэтому я использую ng-form
создавать "вложенные" формы на лету, потому что в документации сказано, что я могу затем использовать проверку этих динамически созданных входных данных.
Хотя это, кажется, работает в HTML, я не вижу, как получить доступ к этим динамически созданным формам и связанным полям проверки в контроллере. В частности, когда пользователь изменяет ввод, я использую свойство формы $ dirty, чтобы вызвать кнопку, чтобы сообщить пользователю о внесении изменений. Все идет нормально. Однако после внесения изменений я хочу $setPristine()
на поле, чтобы указать, что изменения были установлены. Могут быть и другие способы обеспечить фиксацию изменений на каждом входе, прежде чем я разрешу фиксацию основной формы, но это было лучшее, что я мог придумать.
К сожалению, хотя в документации сказано, что если я назову ng-форму, она будет распространена на $scope
объект, я не могу найти способ получить к нему доступ. $scope.dynamic_form
не определено
Вот плункер, показывающий, что я имею в виду:
Спасибо!
[РЕДАКТИРОВАТЬ] Просто чтобы добавить к проблеме, что работает для этого конкретного примера, чтобы добавить к ng-click
на динамически создаваемом входе:
ng-click="namesForm.name.$setPristine();clean()"
Но у меня все еще нет доступа к динамически создаваемой форме в контроллере. Я хотел бы, например, добавить наблюдателя в namesForm.name.$pristine
так что я могу установить mainForm.$setValidity(false)
всякий раз, когда подформа $dirty
запретить пользователю отправлять основную форму до тех пор, пока не будут приняты все изменения в форме.
Итак, в двух словах, проблема в том, как получить доступ в родительском контроллере к значениям проверки динамически создаваемого вложенного ngForm?
1 ответ
Обновлено 2015-01-17:
Как отметил Леблан Менезес в комментариях, Angular 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>
Вот обновленный Plunker, показывающий новое поведение: http://plnkr.co/edit/Lxem5HJXe0UCvslqbJr3?p=preview