2012-09-23 9 views
82

ich ein Formular mit einigen dynamischen Fragen (Geige here) auffüllen möchten:Wie kann ich einen dynamischen Modellnamen in AngularJS festlegen?

<div ng-app ng-controller="QuestionController"> 
    <ul ng-repeat="question in Questions"> 
     <li> 
      <div>{{question.Text}}</div> 
      <select ng-model="Answers['{{question.Name}}']" ng-options="option for option in question.Options"> 
      </select> 
     </li> 
    </ul> 

    <a ng-click="ShowAnswers()">Submit</a> 
</div> 
​ 
function QuestionController($scope) { 
    $scope.Answers = {}; 

    $scope.Questions = [ 
    { 
     "Text": "Gender?", 
     "Name": "GenderQuestion", 
     "Options": ["Male", "Female"]}, 
    { 
     "Text": "Favorite color?", 
     "Name": "ColorQuestion", 
     "Options": ["Red", "Blue", "Green"]} 
    ]; 

    $scope.ShowAnswers = function() 
    { 
     alert($scope.Answers["GenderQuestion"]); 
     alert($scope.Answers["{{question.Name}}"]); 
    }; 
}​ 

Alles funktioniert, außer das Modell buchstäblich Antworten [ „{{question.Name}}“], statt der ausgewerteten Antworten ["Geschlechtsfrage"]. Wie kann ich diesen Modellnamen dynamisch festlegen?

Antwort

112

http://jsfiddle.net/DrQ77/

Sie können einfach JavaScript-Ausdruck in ng-model setzen.

+1

Ich schwöre, dass ich das versucht. Vielen Dank. Ich ging eigentlich eine andere Route, und stellen Sie das Modell nur in Frage. Antwort (ich werde eine aktualisierte Geige in einem Bit), die sich als eine direktere Antwort (muss aus der jQuery Denkweise), aber Es ist großartig zu wissen, dass ich es tatsächlich so machen kann, wie ich es ursprünglich für die Zukunft geplant hatte. Danke noch einmal! –

+5

Aktualisierte Geige: http://jsfiddle.net/2AwLM/23/ –

+0

Falls dies jemand anderem hilft, hatte ich ähnliche Probleme, aber mein Problem war, dass ich 'ng-pattern = "field.pattern" 'wann Was ich wirklich wollte, war 'pattern =" {{field.pattern}} "'.Irgendwie verwirrend, dass eckig normalerweise einen Helfer für dynamische Attribute bietet, aber diesmal schrieb es seine eigene clientseitige Validierung und gab ihm den gleichen Namen. – colllin

10

Was ich am Ende ist, etwas zu tun wie folgt aus:

In der Steuerung:

link: function($scope, $element, $attr) { 
    $scope.scope = $scope; // or $scope.$parent, as needed 
    $scope.field = $attr.field = '_suffix'; 
    $scope.subfield = $attr.sub_node; 
    ... 

so in den Vorlagen konnte ich total dynamische Namen verwenden, und zwar nicht nur unter einem bestimmten Element hartcodiert (wie in Ihrem "Antworten" Fall):

<textarea ng-model="scope[field][subfield]"></textarea> 

Hoffe, dass dies hilft.

3

Um die von @abourget bereitgestellte Antwort vollständiger zu machen, könnte der Wert von scopeValue [field] in der folgenden Codezeile undefiniert sein. Dies führt zu einem Fehler würde, wenn Teilfeld Einstellung:

<textarea ng-model="scopeValue[field][subfield]"></textarea> 

Eine Möglichkeit, dieses Problem zu lösen, ist durch ein Attribut ng Fokus Hinzufügen = „Nullsafe (Feld)“, so würde der Code aussehen wie die folgende Liste:

<textarea ng-focus="nullSafe(field)" ng-model="scopeValue[field][subfield]"></textarea> 

Dazu Nullsafe (Feld) in einem Controller wie unten definiert:

$scope.nullSafe = function (field) { 
    if (!$scope.scopeValue[field]) { 
    $scope.scopeValue[field] = {}; 
    } 
}; 

Dies würde garantieren, dass scopeValue [field] undefiniert ist nicht vor einem beliebigen Wert scopeValue Einstellung [field] [Teilfeld ].

Hinweis: Sie können nicht ng-change = "nullSafe (field)" verwenden, um dasselbe Ergebnis zu erzielen, da ng-change nach dem Ändern des ng-Modells erfolgt, was zu einem Fehler führen würde, wenn scopeValue [field] ist nicht definiert.

27

Sie können etwas wie dieses verwenden scopeValue[field], aber wenn Ihr Feld in einem anderen Objekt ist, benötigen Sie eine andere Lösung.

alle Arten von Situationen zu lösen, können Sie diese Anweisung verwenden:

this.app.directive('dynamicModel', ['$compile', '$parse', function ($compile, $parse) { 
    return { 
     restrict: 'A', 
     terminal: true, 
     priority: 100000, 
     link: function (scope, elem) { 
      var name = $parse(elem.attr('dynamic-model'))(scope); 
      elem.removeAttr('dynamic-model'); 
      elem.attr('ng-model', name); 
      $compile(elem)(scope); 
     } 
    }; 
}]); 

Html Beispiel:

<input dynamic-model="'scopeValue.' + field" type="text"> 
+2

speicherte meinen Tag :) – WeMakeSoftware

+0

Funktioniert wie erwartet. – C0ZEN

+1

Yay! Das habe ich gebraucht! Vielen Dank! – Snapman

Verwandte Themen