Як я можу встановити назву динамічної моделі в 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}}"]);
    };
}​

Все працює, крім моделі, це буквально відповіді ["{{question.Name}}"], замість оцінених відповідей ["GenderQuestion"]. Як я можу динамічно встановити цю назву моделі?

Відповіді:


121

http://jsfiddle.net/DrQ77/

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


1
Клянусь, я пробував це. Велике спасибі. Я насправді пішов іншим шляхом, і просто встановив модель для запитання. Відповісти (трохи викладу оновлену скрипку), що виявилося більш прямою відповіддю (потрібно вийти з мислення jQuery), але чудово знати, що я справді можу зробити це так, як я спочатку планував на майбутнє. Знову дякую!
Mike Pateras

Якщо це допомагає комусь ще, у мене були подібні проблеми, але моя проблема полягала в тому, що я використовував, ng-pattern="field.pattern"коли те, що я насправді хотів, було pattern="{{field.pattern}}". Начебто плутаєш, що angular зазвичай надає помічник для динамічних атрибутів, але цього разу написав власну перевірку на стороні клієнта і дав йому те саме ім'я.
colllin

Чому ви вирішили створити порожній об’єкт (відповіді), коли для цього у вас немає фактичної мети? Ви, здається, використовуєте її лише в ng-моделі, крім цієї, ціль, здається, не існує, то чому б її взагалі не опустити і зробити так, щоб вона працювала? Не могли б ви пояснити?
Девнер,

Я просто спробував мінімально змінити вихідний код. Якщо ви подивитесь на переглянутий код Майка ( jsfiddle.net/2AwLM/23 ), він вирішив його позбутися.
Тош

ЩИРО дякую за це. Мені дуже допомогло. Дивіться тут: 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 [поле] у наступному рядку коду може бути невизначеним. Це призведе до помилки при встановленні підполя:

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

Одним із способів вирішення цієї проблеми є додавання атрибута ng-focus = "nullSafe (поле)", щоб ваш код мав виглядати так:

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

Потім ви визначаєте nullSafe (поле) у контролері, як показано нижче:

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

Це гарантувало б, що scopeValue [поле] не визначено перед встановленням будь-якого значення для scopeValue [поле] [підполе].

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


1

Або ви можете використовувати

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.