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

StackOverflow https://stackoverflow.com//questions/24020503

Вопрос

Я пытаюсь сгенерировать редактируемый список, используя 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top