【问题标题】:Bind dynamically set ng-model attribute for text field为文本字段动态绑定设置 ng-model 属性
【发布时间】:2016-10-24 15:22:54
【问题描述】:

搜索了几个小时后,我仍然无法找到问题的答案。我正在使用基于数据库值的文本字段填充动态表单,但无法成功将字段绑定到我的模型。场景如下:

我的控制器中有一个“项目”模型,其中包含许多项目相关信息(名称、开始日期、参与者、类别等),但现在让我们只关注“project.name”属性。在数据库中,我为“表单”配置了许多相关字段,其中每个字段都有一个属性,该属性指向它在我的视图模型中对应的属性(例如“project.name”)。在运行时,我将这些字段动态添加到 HTML 表单中,并尝试将 ng-model 属性设置为“modelBinding”值,在本例中为“project.name”。

<div ng-repeat="formField in form.formFields">
            <input ng-model="formField.modelBinding" /></div>

这将导致一个文本框被添加到我的表单中,其中 ng-model="formField.modelBinding" 和文本框值 = 'project.data'。

我想要实现的是设置 ng-model = 'project.data',换句话说,用 formField.modelBinding 的 value 替换 formField.modelBinding。

一种看起来合乎逻辑的方法是

<input ng-model = "{{formField.modelBinding}}" />

但这显然行不通。我尝试使用 ng-bind-html 插入 HTML 标签,但这似乎只适用于 ng-bind,不适用于 ng-model。

有什么建议吗?

【问题讨论】:

  • 我不确定我是否能理解这个问题。您能否也分享一下数据中的 sn-p?

标签: angularjs


【解决方案1】:

假设您尝试使用 formField 中的名称将值绑定到模型,您可以创建一个指令(又名 ngModelName)以从此值按名称绑定模型。

观察:我的第一个想法是使用像model[formField.modelBinding] 这样的简单访问器,它将formField.modelBinding 简单地绑定到作用域上的model 成员。但是,我没有使用属性访问器,因为它会创建一个由 formField.modelBinding 值命名的属性,而不是预期的正确对象层次结构。例如,在这个问题上描述的情况下,project.data 将创建一个对象 { 'project.data': 'my data' },但不会创建应有的 { 'project': { data: 'my data'}}

angular.module('myApp', [])
  .directive('ngModelName', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        priority: 1000,
        link: function (scope, element, attrs) {
          
          scope.$watch(attrs.ngModelName, function(ngModelName) {
                // no need to bind a model
                if (attrs.ngModel == ngModelName || !ngModelName) return;

                element.attr('ng-model', ngModelName);
                
                // remove ngModel if it's empty
                if (ngModelName == '') {
                    element.removeAttr('ng-model');
                }

                // clean the previous event handlers,
                // to rebinded on the next compile
                element.unbind();

                //recompile to apply ngModel, and rebind events
                $compile(element)(scope);
            });
          }
    };
  }])
  .controller('myController', function ($scope) {
    $scope.form = {
      formFields: [
        {
          modelBinding: 'model.project.data'
        }
      ]
    };
  
    $scope.model = {};
  });

angular.element(document).ready(function () {
  angular.bootstrap(document, ['myApp']);  
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="myController">
  <div ng-repeat="formField in form.formFields">
      <input ng-model-name="formField.modelBinding" placeholder="{{ formField.modelBinding }}" />
  </div>
  <div>
    <pre>{{ model | json }}</pre>
  </div>
</div>

【讨论】:

  • 嗯,这看起来有点矫枉过正。为什么不直接使用[xxx] 属性访问器?
  • @VasilyLiaskovsky 这也是我的第一个想法。但是,我没有使用[xxx] 属性访问器,因为[xxx] 将创建一个名为xxx 的属性,而不是预期的正确对象层次结构。例如,在这个问题上描述的情况,project.data 将创建一个像{'project.data': 'data'} 而不是{project: {data: 'data'}} 的对象,这可能不是问题,但对我来说听起来不正确。
  • 此解决方案有效!我早期尝试编写自定义指令,但是对于 Angular 来说是新手,它并没有达到我的预期。谢谢!
【解决方案2】:

我猜“modelBinding”属性有表单域的模型名称,所以,在这种情况下你应该这样做:

<div ng-repeat="formField in form.formFields">
        <input ng-model="form.formFields[formField.modelBinding]" />
</div>

使用modelBinding作为key从formFields中检索。

【讨论】:

    猜你喜欢
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    相关资源
    最近更新 更多