如何在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”]。如何动态设置型号名称?

Answers:


121

http://jsfiddle.net/DrQ77/

您只需将javascript表达式放入中ng-model


1
我发誓我尝试过。非常感谢你。我实际上走了一条不同的路线,只是将模型设置为问题。答案(我会稍等一下)很高兴知道我确实可以按照我最初为未来计划的方式做到这一点。再次感谢!
Mike Pateras

万一这对其他人有帮助,我也会遇到类似的问题,但是我的问题是我在ng-pattern="field.pattern"真正想要的时间是在使用pattern="{{field.pattern}}"。有点令人困惑的是,Angular通常为动态属性提供了一个帮助器,但是这次编写了它自己的客户端验证,并为其赋予了相同的名称。
Colllin 2013年

当您没有实际目的时,为什么决定创建一个空对象(答案)?您似乎只在ng-model中使用它,除此之外似乎没有任何用途。那么为什么不完全忽略它并使其工作呢?你能澄清一下吗?
Devner

我只是尝试对原始代码进行最小的更改。如果您查看Mike的修改后的代码(jsfiddle.net/2AwLM/23),他决定摆脱它。
Tosh 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 '16

2
真好 但是仍然希望我们可以使用ng-model="{{ variable }}":)
davidkonrad '16

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(field):

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

这将确保在将任何值设置为scopeValue [field] [subfield]之前,未定义scopeValue [field]。

注意:您不能使用ng-change =“ nullSafe(field)”来获得相同的结果,因为ng-change是在ng-model更改后发生的,如果scopeValue [field]未定义,则会引发错误。


1

或者你可以使用

<select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
        </select>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.