2012-09-23 6 views
82

Chcę wypełnić formularz z pytaniami niektórych dynamicznych (skrzypce here):Jak ustawić nazwę modelu dynamicznego w 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}}"]); 
    }; 
}​ 

Wszystko działa, z wyjątkiem model jest dosłownie odpowiedzi [ „{{question.Name}}”] zamiast ocenianego odpowiedzi ["GenderQuestion"]. Jak mogę dynamicznie ustawić tę nazwę modelu?

Odpowiedz

112

http://jsfiddle.net/DrQ77/

można po prostu umieścić wyrażenie javascript w ng-model.

+1

Przysięgam, że próbowałem. Dziękuję Ci bardzo. Poszedłem na inną trasę i po prostu ustawiłem model na pytanie. Odpowiedź (trochę zaktualizuję skrzypce), co okazało się bardziej bezpośrednią odpowiedzią (muszę wyjść ze sposobu myślenia jQuery), ale wspaniale jest wiedzieć, że mogę zrobić to tak, jak pierwotnie planowałem na przyszłość. Dzięki jeszcze raz! –

+5

Zaktualizowane skrzypce: http://jsfiddle.net/2AwLM/23/ –

+0

Jeśli to pomogło komuś innemu, miałem podobne problemy, ale moim problemem było to, że używałem 'ng-pattern =" field.pattern "' to, czego naprawdę chciałem, to 'pattern =" {{field.pattern}} "'.Kłopotliwe, że kątowe zwykle dostarcza pomocnika dla dynamicznych atrybutów, ale tym razem napisał własną walidację po stronie klienta i nadał mu tę samą nazwę. – colllin

10

Co skończyło się robi coś takiego:

W regulatorze:

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

więc w szablonach można używać nazw całkowicie dynamiczne, a nie tylko pod pewnym zakodowanej elementu (jak w przypadku "Answers"):

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

Mam nadzieję, że to pomoże.

3

Aby odpowiedź udzielona przez @ablet była bardziej kompletna, wartość parametru scopeValue [pole] w poniższym wierszu kodu może być niezdefiniowana. Spowodowałoby to błąd przy ustawianiu podpole:

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

Jednym ze sposobów rozwiązania tego problemu jest dodanie atrybutu NG-Focus = „nullSafe (pole)”, więc Twój kod będzie wyglądać następująco:

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

Następnie należy zdefiniować nullSafe (pole) w kontrolerze jak poniżej:

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

byłoby to zagwarantować, że scopeValue [pole] nie jest niezdefiniowany przed ustawieniem żadnej wartości do scopeValue [pola] [podpolu ].

Uwaga: Nie można użyć polecenia ng-change = "nullSafe (pole)" w celu uzyskania tego samego wyniku, ponieważ zmiana ng następuje po zmianie modelu ng, co spowodowałoby błąd, jeśli parametr scopeValue [pole] jest niezdefiniowany.

27

Możesz użyć czegoś takiego: scopeValue[field], ale jeśli twoje pole jest w innym obiekcie, będziesz potrzebować innego rozwiązania.

Aby rozwiązać wszelkiego rodzaju sytuacjach można skorzystać z tej dyrektywy:

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 przykład:

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

zapisał mój dzień :) – WeMakeSoftware

+0

Działa zgodnie z oczekiwaniami. – C0ZEN

+1

Yay! Tego właśnie potrzebowałem! Dziękuję Ci! – Snapman