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

AngularJS: поля, добавленные динамически, не зарегистрированы на FormController

У меня есть следующая форма статическая в AngularJS:

<form name="myForm" class="form-horizontal">

  <label>First Name:</label>
  <input type="text" name="first_name" ng-model="entity.first_name">

  <label>Last Name:</label>
  <input type="text" name="last_name" ng-model="entity.last_name">

</form>

Angular создает FormController для меня и публикует его в области (под именем формы). Это означает, что у меня есть доступ к следующим свойствам:

$scope.myForm.first_name.$error
$scope.myForm.last_name.$invalid
...

Это супер полезно!

Но в моем случае я строю форму динамически, используя директивы:

<form name="myForm" class="form-horizontal">

  <field which="first_name"></field>
  <field which="last_name"></field>

</form>

Директивы <field> не разрешают действительные элементы <input> до тех пор, пока через некоторое время (после того, как я извлек некоторые данные с сервера, связал директивы и т.д.).

Проблема заключается в том, что на контроллере формы не определены свойства поля, как если бы динамические поля не регистрировались в FormController:

// The following properties are UNDEFINED (but $scope.myForm exists)
$scope.myForm.first_name
$scope.myForm.last_name

Любая идея, почему? Любое решение/обходное решение?

Вы можете увидеть весь код в этом jsFiddle:
http://jsfiddle.net/vincedo/3wcYV/

4b9b3361

Ответ 1

Обновление 7/31/2015 Это исправлено с 1,3, см. здесь: https://github.com/angular/angular.js/issues/1404#issuecomment-125805732 p >

Оригинальный ответ Это, к сожалению, короткое появление AngularJS на данный момент. Angular проверка формы не работает с динамически именованными полями. Вы можете добавить следующее в нижней части своего HTML, чтобы точно узнать, что происходит:

<pre>{{myForm|json}}</pre>

Как вы можете видеть, Angular не получает имя динамического ввода правильно. В настоящее время существует работа с вовлеченными вложенными формами, которые могут стать отвратительными, но они действительно работают, и (с небольшой дополнительной работой) без проблем отправят родительскую форму.

Если вы хотите, вы можете получить больше поддержки для проблемы: GitHub Issue - проверка динамического элемента. В любом случае, здесь код:

http://jsfiddle.net/langdonx/6H8Xx/2/

HTML:

<div data-ng-app>
    <div data-ng-controller="MyController">
        <form id="my_form" name="my_form" action="/echo/jsonp/" method="get">
            <div data-ng-repeat="field in form.data.fields">
                <ng-form name="form">
                    <label for="{{ field.name }}">{{ field.label }}:</label>
                    <input type="text" id="{{ field.name }}" name="{{field.name}}" data-ng-model="field.data" required>
                    <div class="validation_error" data-ng-show="form['\{\{field.name\}\}'].$error.required">Can't be empty.</div>

                </ng-form>
            </div>
            <input type="submit" />
        </form>
    </div>
</div>

JavaScript:

MyController.$inject = ["$scope"];

function MyController($scope) {
    $scope.form = {};
    $scope.form.data = {};
    $scope.form.data.fields = []

    var f1 = {
        "name": "input_1",
        "label": "My Label 1",
        "data": ""
    };
    var f2 = {
        "name": "input_2",
        "label": "My Label 2",
        "data": ""
    };

    $scope.form.data.fields.push(f1);
    $scope.form.data.fields.push(f2);
}

Ответ 2

Я столкнулся с подобной проблемой сам, и что я сделал, чтобы обойти это, было поместить имя поля, прежде чем вызывать $compile на шаблоне. Простой string.replace сделал трюк. Тогда это было возможно только потому, что я получал шаблоны полей через http и имел доступ к тексту шаблона.

update: вот скрипка с небольшим взломом, чтобы ваш пример работал.

app.directive('field', function($compile) {
    var linker= function(scope, element){

    var template = '<input type="text" name="{{fname}}" ng-model="model">'
    .replace('{{fname}}', scope.fname);
        element.html(template)
        $compile(element.contents())(scope)
    }
  return {
    restrict: 'E',
    scope: {
      fname: '=',
      model: '='
    },

    replace: true,
      link: linker
  };
});

http://jsfiddle.net/2Ljgfsg9/4/