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 ["GenderQuestion"]ではなく、モデルが文字通りAnswers ["{{question.Name}}"]であることを除いて、すべてが機能します。そのモデル名を動的に設定するにはどうすればよいですか?

回答:


121

http://jsfiddle.net/DrQ77/

あなたは単にJavaScript式をに置くことができng-modelます。


1
私はそれを試したと誓います。どうもありがとうございました。私は実際には別のルートに進み、モデルを質問に設定しました。回答(更新されたフィドルを少し出していきます)は、より直接的な答えであることがわかりました(jQueryの考え方から抜け出す必要があります)が、確かに、私が当初計画していた方法でそれを行うことができることを知ってうれしいです。再度、感謝します!
Mike Pateras、2012

これが他の人に役立つ場合、私は同様の問題を抱えていましたが、私の問題は、私がng-pattern="field.pattern"本当に望んでいたものを使用していたということでしたpattern="{{field.pattern}}"。その混乱は一種の混乱を招き、通常は動的属性のヘルパーを提供しますが、今回は独自のクライアント側検証を記述し、同じ名前を付けました。
colllin 2013年

実際の目的がないのに、なぜ空のオブジェクト(Answers)を作成することにしたのですか?ng-modelのみで使用しているようですが、これ以外に目的はないようですので、全部省略してそのまま動作させてみませんか?明確にしていただけませんか?
Devner 2014

元のコードから最小限の変更を加えようとしただけです。マイクの改訂されたコード(jsfiddle.net/2AwLM/23)を見ると、彼はそれを取り除くことにしました。
2014

本当にありがとうございました。私を大いに助けてくれました。ここを参照してください: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;
  ...

テンプレートでは、特定のハードコードされた要素(「Answers」の場合のように)だけでなく、完全に動的な名前を使用できます。

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

お役に立てれば。


3

@abourgetによって提供される回答をより完全にするために、次のコード行のscopeValue [field]の値を未定義にすることができます。これにより、サブフィールドの設定時にエラーが発生します。

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

この問題を解決する1つの方法は、属性ng-focus = "nullSafe(field)"を追加することです。そのため、コードは次のようになります。

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

次に、以下のようにコントローラーでnullSafe(field)を定義します。

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

これにより、scopeValue [field] [subfield]に値を設定する前に、scopeValue [field]が未定義にならないことが保証されます。

注:ng-change = "nullSafe(field)"を使用して同じ結果を達成することはできません。ng-modelが変更された後にng-changeが発生し、scopeValue [field]が定義されていない場合にエラーがスローされるためです。


1

またはあなたが使うことができます

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.