2013-04-05 10 views
28

Mam następujący statyczny forma angularjs:angularjs: Pola dodawane dynamicznie nie są zarejestrowane na FormController

<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> 

kątowa tworzy FormController dla mnie i publikuje ją w zakres (pod nazwą formularza). Co oznacza, że ​​mam dostęp do właściwości takich jak:

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

Jest to bardzo przydatne!

Ale w moim przypadku buduję formę dynamicznie, wykorzystujące dyrektywami:

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

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

</form> 

W <field> dyrektyw nie rozwiązuje rzeczywistych <input> elementów, aż po pewnym czasie (po jakie przyniosła pewne dane z serwera, powiązane dyrektywy itp.).

Problemem jest to, że nie ma właściwości pól są określone w sterowniku formy, jakby pola dynamiczne nie zarejestrować się w FormController:

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

jakiś pomysł, dlaczego? Jakiekolwiek rozwiązanie/obejście?

Można zobaczyć cały kod w tym jsFiddle:
http://jsfiddle.net/vincedo/3wcYV/

+0

Może pokażesz nam kod dla 'field' dyrektywy? Podejrzewam, że jest to problem z zasięgiem. – Intelekshual

+0

Pewnie! Zobacz: jsFiddle: http://jsfiddle.net/vincedo/3wcYV/ – AngularChef

Odpowiedz

24

Aktualizacja 31.07.2015 ta została ustalona od 1.3, zobacz tutaj: https://github.com/angular/angular.js/issues/1404#issuecomment-125805732

Original odpowiedzi ten to niestety krótkie przybycie AngularJS w tej chwili. Sprawdzanie poprawności formularza Angular nie działa z dynamicznie nazwanymi polami. Można dodać następujące na końcu kodu HTML, aby zobaczyć dokładnie, co się dzieje:

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

Jak widać, kątowy nie jest uzyskanie dynamicznego input name prawo. Obecnie trwają prace nad wykorzystaniem zagnieżdżonych formularzy, które mogą stać się nieprzyjemne, ale działa i (przy odrobinie dodatkowej pracy) bez problemu przesyła formularz nadrzędny.

Jeśli chcesz, możesz dodać więcej wsparcia dla problemu: GitHub Issue - dynamic element validation. Tak czy inaczej, oto kod:

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); 
} 
+1

Dziękujemy za wyjaśnienie i obejście tego problemu. Dla tych, którzy to czytają, skończyłem generowanie formularza po stronie serwera znaczników, co ma kilka zalet: 1) omija wspomniany wyżej problem pól dynamicznych; 2) pozwala mi korzystać ze znanej biblioteki formularzy (w moim przypadku [WTForms] (http://wtforms.simplecodes.com/)); 3) unika tworzenia obiektu JavaScript reprezentującego definicję formularza; 4) ściślejsza integracja modeli i formularzy (ponieważ wszystkie one są zdefiniowane przez kod po stronie serwera). – AngularChef

2

wpadłem na podobny problem siebie i to, co zrobiłem, aby obejść to było wstawić nazwę pola przed wywołaniem $ compile na szablonie. Prosty string.replace zrobił lewę. Z drugiej strony było to możliwe tylko dlatego, że otrzymywałem szablony pól za pośrednictwem protokołu http i miałem dostęp do tekstu szablonu.

zmiana: o to skrzypce z małym hack, aby twój przykład pracować

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/

Powiązane problemy