Угловой NG-повтор с NG-формы, доступ к проверке в контроллере

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

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

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

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

plnk

Спасибо!

[РЕДАКТИРОВАТЬ] Просто чтобы добавить к проблеме, что работает для этого конкретного примера, чтобы добавить к 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

Другие вопросы по тегам