Подтвердить что ты не робот

Angular ng-repeat с ng-формой, доступ к проверке в контроллере

Я пытаюсь создать редактируемый список, используя ng-repeat. Я хочу напомнить пользователю обновить все изменения до перехода, поэтому я использую ng-form для создания "вложенных" форм "на лету", потому что в документации говорится, что я могу использовать валидацию на этих динамически создаваемых входах.

Хотя это работает в HTML, я не вижу, как получить доступ к этим динамически созданным формам и связанным полям проверки в контроллере. В частности, когда пользователь меняет ввод, я использую свойство $dirty формы, чтобы вызвать кнопку, чтобы сообщить пользователю о внесении изменений. Все идет нормально. Однако, как только изменения будут зафиксированы, я хочу $setPristine() в поле указать, что изменения были установлены. Могут быть другие способы обеспечения того, чтобы изменения были зафиксированы на каждом входе, прежде чем я разрешаю основную форму, но это было лучшее, что я мог придумать.

К сожалению, несмотря на то, что в документации указано, что если я назову ng-форму, она будет распространена на объект $scope, я не могу найти способ получить к ней доступ. $scope.dynamic_form - undefined.

Вот плункер, показывающий, что я имею в виду:

plnk

Спасибо!

[EDIT] Чтобы добавить к проблеме, что работает для этого конкретного примера, нужно добавить к ng-click динамически созданный ввод:

ng-click="namesForm.name.$setPristine();clean()"

Но у меня все еще нет доступа к динамически созданной форме в контроллере. Я хотел бы, например, добавить наблюдателя к namesForm.name.$pristine, чтобы я мог установить mainForm.$setValidity(false) всякий раз, когда подформация $dirty, чтобы пользователь не отправлял основную форму до тех пор, пока все изменения подформы не будут были совершены.

Итак, вкратце, проблема заключается в том, как получить в родительском контроллере значения проверки динамически созданной вложенной ngForm?

4b9b3361

Ответ 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 & ​​lt; = 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 при нажатии кнопки "clean".

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