【问题标题】:How can I set a dynamic model name in AngularJS?如何在 AngularJS 中设置动态模型名称?
【发布时间】:2012-09-23 15:32:10
【问题描述】:

我想用一些动态问题填充表单(小提琴here):

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

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    http://jsfiddle.net/DrQ77/

    您可以简单地将javascript表达式放入ng-model

    【讨论】:

    • 我发誓我试过了。非常感谢。我实际上走了一条不同的路线,只是将模型设置为 question.Answer(稍后我会发布一个更新的小提琴),结果证明这是一个更直接的答案(必须摆脱 jQuery 思维方式),但是很高兴知道我确实可以按照我最初为未来计划的方式去做。再次感谢!
    • 如果这对其他人有帮助,我遇到了类似的问题,但我的问题是我使用的是ng-pattern="field.pattern",而我真正想要的是pattern="{{field.pattern}}"。有点令人困惑的是,角度通常为动态属性提供帮助,但这次编写了自己的客户端验证并给了它相同的名称。
    • 当您没有实际用途时,为什么决定创建一个空对象(答案)?您似乎只在 ng-model 中使用它,除此之外,似乎没有任何目的。那么为什么不完全省略它并让它以这种方式工作呢?你能澄清一下吗?
    • 我只是尝试对原始代码进行最小的更改。如果你看一下 Mike 修改后的代码 (jsfiddle.net/2AwLM/23),他决定去掉它。
    • 非常感谢您。帮了我很多。见这里:stackoverflow.com/questions/34081903/…
    【解决方案2】:

    您可以使用类似 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">
    

    【讨论】:

    • 按预期工作。
    • 耶!这就是我需要的!谢谢!
    • 不错。但仍然希望我们可以使用ng-model="{{ variable }}" :)
    【解决方案3】:

    我最终做的是这样的:

    在控制器中:

    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>
    

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      为了使@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] 为未定义。

      【讨论】:

        【解决方案5】:

        或者你可以使用

        <select [(ngModel)]="Answers[''+question.Name+'']" ng-options="option for option in question.Options">
                </select>
        

        【讨论】:

          猜你喜欢
          • 2014-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-10
          • 1970-01-01
          相关资源
          最近更新 更多