2012-09-23 24 views
82

voglio compilare un modulo con alcune domande dinamiche (violino here):Come posso impostare un nome di modello dinamico in AngularJS?

<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}}"]); 
    }; 
}​ 

Tutto funziona, tranne il modello è letteralmente Answers [ "{{}} question.Name"], al posto delle risposte valutati [ "GenderQuestion"]. Come posso impostare dinamicamente il nome di questo modello?

risposta

112

http://jsfiddle.net/DrQ77/

Si può semplicemente inserire javascript espressione in ng-model.

+1

Giuro ho provato. Grazie mille. In realtà ho seguito un percorso diverso, e ho semplicemente impostato il modello su cui porre domande. Risposta (farò uscire un violino aggiornato in un po '), che si è rivelata una risposta più diretta (devo uscire dalla mentalità jQuery), ma è bello sapere che posso, in effetti, farlo nel modo in cui inizialmente avevo programmato il futuro. Grazie ancora! –

+5

Fiddle aggiornato: http://jsfiddle.net/2AwLM/23/ –

+0

Nel caso in cui questo aiuti qualcun altro, stavo riscontrando problemi simili, ma il mio problema era che stavo usando 'ng-pattern =" field.pattern "' quando quello che volevo veramente era 'pattern =" {{field.pattern}} "'.Un po 'di confusione che l'angolare di solito fornisce un aiuto per gli attributi dinamici, ma questa volta ha scritto la propria convalida sul lato client e gli ha dato lo stesso nome. – colllin

10

Quello che ho finito per fare è qualcosa di simile:

Nel controllore:

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

così nei modelli ho potuto utilizzare nomi completamente dinamici, e non solo sotto un certo elemento hard-coded (come nel caso "Answers"):

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

Spero che questo aiuti.

3

Per rendere la risposta fornita da @abourget più completa, il valore di scopeValue [campo] nella seguente riga di codice potrebbe non essere definito. Ciò si tradurrebbe in un errore durante l'impostazione sottocampo:

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

Un modo per risolvere questo problema è con l'aggiunta di un attributo ng-focus = "nullSafe (campo)", in modo che il codice sarebbe apparire come il qui sotto:

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

Poi si definiscono nullSafe (campo) in un controller come di seguito:

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

Ciò garantirebbe che scopeValue [campo] non è definito prima di impostare qualsiasi valore per scopeValue [campo] [sottocampo ].

Nota: non è possibile utilizzare ng-change = "nullSafe (campo)" per ottenere lo stesso risultato perché ng-change si verifica dopo la modifica del modello ng, che genera un errore se scopeValue [campo] è indefinito.

27

È possibile utilizzare qualcosa come questo scopeValue[field], ma se il vostro campo è in un altro oggetto avrete bisogno di un'altra soluzione.

Per risolvere tutti i tipi di situazioni, è possibile utilizzare questa direttiva:

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

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

salvato la mia giornata :) – WeMakeSoftware

+0

Funziona come previsto. – C0ZEN

+1

Yay! Questo è quello di cui avevo bisogno! Grazie! – Snapman

Problemi correlati