Как я могу установить имя динамической модели в AngularJS?

91

Я хочу заполнить форму некоторыми динамическими вопросами (скрипт здесь ):

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

Все работает, кроме модели буквально Answers ["{{question.Name}}"], а не оцениваемых Answers ["GenderQuestion"]. Как я могу установить это имя модели динамически?

Майк Патерас
источник

Ответы:

121

http://jsfiddle.net/DrQ77/

Вы можете просто вставить выражение javascript ng-model.

Тош
источник
1
Клянусь, я пробовал это. Большое спасибо. На самом деле я пошел другим путем и просто поставил модель на вопрос. Ответ (я немного расскажу об обновленной скрипке), который оказался более прямым ответом (нужно выйти из образа мышления jQuery), но Приятно знать, что я действительно могу сделать это так, как я изначально планировал на будущее. Еще раз спасибо!
Майк Патерас,
Если это кому-то поможет, у меня были похожие проблемы, но моя проблема заключалась в том, что я использовал ng-pattern="field.pattern"то, что мне действительно нужно pattern="{{field.pattern}}". Непонятно, что angular обычно предоставляет помощника для динамических атрибутов, но на этот раз написал собственную проверку на стороне клиента и дал ей то же имя.
colllin
Почему вы решили создать пустой объект (Ответы), когда у вас нет для этого реальной цели? Кажется, вы используете его только в ng-модели, и кроме этого, похоже, нет никакой цели. Так почему бы не опустить его вообще и не заставить его работать таким образом? Не могли бы вы уточнить?
Devner
Я просто попытался внести минимальные изменения в исходный код. Если вы посмотрите на исправленный код Майка ( jsfiddle.net/2AwLM/23 ), он решил избавиться от него.
Tosh
Спасибо вам большое за это. Мне очень помогли. См. Здесь: stackoverflow.com/questions/34081903/…
Альберт
31

Вы можете использовать что-то подобное scopeValue[field], но если ваше поле находится в другом объекте, вам понадобится другое решение.

Для решения любых ситуаций вы можете использовать эту директиву:

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:

<input dynamic-model="'scopeValue.' + field" type="text">
Уильям Векл
источник
Работает как положено.
C0ZEN
1
Ура! Это то, что мне было нужно! Спасибо!
Snapman
2
Ницца. Но все же хотелось бы, чтобы мы могли просто использовать ng-model="{{ variable }}":)
davidkonrad
13

В итоге я сделал что-то вроде этого:

В контроллере:

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

поэтому в шаблонах я мог использовать полностью динамические имена, а не только под определенным жестко запрограммированным элементом (как в вашем случае «Ответы»):

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

Надеюсь это поможет.

превозносить
источник
3

Чтобы сделать ответ, предоставленный @abourget, более полным, значение scopeValue [field] в следующей строке кода может быть неопределенным. Это приведет к ошибке при установке подполя:

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

Один из способов решения этой проблемы - добавить атрибут ng-focus = "nullSafe (field)", чтобы ваш код выглядел следующим образом:

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

Затем вы определяете nullSafe (поле) в контроллере, как показано ниже:

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

Это гарантирует, что scopeValue [field] не является неопределенным перед установкой любого значения для scopeValue [field] [subfield].

Примечание. Вы не можете использовать ng-change = "nullSafe (field)" для достижения того же результата, потому что ng-change происходит после изменения ng-модели, что приведет к ошибке, если scopeValue [field] не определено.

Максимум
источник
1

Или вы можете использовать

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
Шафак
источник