【问题标题】:Parameterizing the data model in an Angular directive在 Angular 指令中参数化数据模型
【发布时间】:2015-12-17 10:41:09
【问题描述】:

我正在实现一个具有三个选项的控件/小部件,其中只能选择一个,这导致我使用单选按钮。这个小部件必须在各种表单上出现多次,所以我开始(逐步)创建一个专用指令。

指令的模板如下:

<div class="row">
<span class="fieldlabel col-xs-3">{{title}}</span>
<div>
    <label>
        <input type="radio" data-ng-model="modelName" value="{{value1}}">
        {{label1}}
    </label>
    <label>
        <input type="radio" data-ng-model="modelName" value="{{value2}}">
        {{label2}}
    </label>
    <label>
        <input type="radio" data-ng-model="modelName" value="{{value3}}">
        {{label3}}
    </label>
</div>

通过使用自定义指令或在控制器中正确定义/计算标题、标签和值。

我现在面临的最后一个问题是如何为每个这样的小部件指定不同的模型绑定?这个小部件的所有实例当前共享它们的模型绑定,这当然不是我需要的。例如,下面虚构示例中的两个 div 都将绑定到“modelName”,但我需要它们绑定到视图控制器中的“annotationsPos”和“menuPos”。

<div my-3option-radiobutton title="Show annotations"></div>
<div my-3option-radiobutton title="Menu position"></div>

如何在自定义指令中指定绑定?

编辑 1 我认为要么我没有真正表达清楚,要么我缺少一些可以帮助我理解所提供答案的元素。

如果我手写 HTML,我会得到这样的:

<div class="row">
<span class="fieldlabel col-xs-3">Position of your annotations</span>
<div>
    <label>
        <input type="radio" data-ng-model="annotationsPos" value="left">
        Left of the element
    </label>
    <label>
        <input type="radio" data-ng-model="annotationsPos" value="middle">
        Through the element
    </label>
    <label>
        <input type="radio" data-ng-model="annotationsPos" value="right">
        Right of the element
    </label>
</div>
<!-- -->
<div class="row">
<span class="fieldlabel col-xs-3">Position of the top menu</span>
<div>
    <label>
        <input type="radio" data-ng-model="menuPos" value="left">
        Top left
    </label>
    <label>
        <input type="radio" data-ng-model="menuPos" value="middle">
        Top middle
    </label>
    <label>
        <input type="radio" data-ng-model="menuPos" value="right">
        Top right
    </label>
</div>
<!-- -->
<div class="row">
<span class="fieldlabel col-xs-3">Position of notifications</span>
<div>
    <label>
        <input type="radio" data-ng-model="notificationPos" value="left">
        Bottom left
    </label>
    <label>
        <input type="radio" data-ng-model="notificationPos" value="middle">
        Bottom middle
    </label>
    <label>
        <input type="radio" data-ng-model="notificationPos" value="right">
        Bottom right
    </label>
</div>

我希望通过 attribute 指令而不是多次复制和粘贴此样板代码:

<div my-3option-radiobutton title="Position of your annotations"></div>
<div my-3option-radiobutton title="Position of system notifications"></div>
<div my-3option-radiobutton title="Position of the top menu"></div>

这些块之间的变化是由标题、值以及最重要的模型属性值构成的。我以一种非优雅的方式涵盖了指令控制器中的标题和值(请参阅下面的进一步说明)。我的问题是我似乎不能:

  1. 确定在何处指定 ng-model AND
  2. 让“生成的”HTML 代码正确引用该模型属性值(即“annotationPos”、“notificationsPos”和“menuPos”)并且
  3. 与父控制器双向绑定

编辑 2 这个plunk 表明@Suresh 的答案是有效的,只是对字段名称进行了少量修改。但是,directive that I have written 不起作用(页面上的所有小部件都绑定到相同的值),可能是因为它是属性指令而不是元素指令。我不想使用后一种类型,因为它对我来说没有意义,最重要的是,这将与其他开发人员一起集成到现有的较大项目中,该项目不使用元素指令。然而,这并不意味着永远不会在项目中使用元素指令。

无论如何,我会继续寻找解决方案。谢谢。

编辑 3 我已经在模板中使用了 ng-repeat 指令,就像@Suresh 所做的那样。使用开发的模板(即手动重复输入标签)不起作用,但我不知道这是否与使用/不使用 ng-repeat 或我“构建”控制器中的值和标签的方式有关.

从我的 plunk 中吸取的教训:即使在小部件的控制器中对 ngModel(如下)进行双向绑定:

  • 除非使用 ng-repeat,否则页面上的所有控件都将绑定到相同的值/变量
  • 如果模板具有data-ng-model="ngModel" 而不是data-ng-model="$parent.ngModel",则不会更新父控制器的绑定模型
scope: {
    ngModel: "="
}

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    'use strict';
    var app = angular.module('MyApp',[]);
    app.directive("myRadiobutton", function () {
        var templateHtml = function () {
            return '<div class="form-group" >' +
                     '<label style="margin-right: 10px"; ng-repeat="(key, option) in options.valueList">' +
                             '<input type="radio" name="myfield" ng-value="option.value" ng-model="$parent.ngModel" ng-required="options.required" />{{option.title}}' +
                     '</label>' +
                 '</div>';
        };
    
        return {
            scope: { options: '=', ngModel: '=' },
            required: ['ngModel'],
            restrict: 'E',
            template: templateHtml,
        };
    });
    app.controller('myController', function ($scope) {
        $scope.radioGender =   {
        "label": "Gender",
        "required": true,
        "className": "",
        "valueList": [
          {
            "title": "Male",
            "value": "1"
          },
          {
            "title": "Female",
            "value": "2"
          },
          {
            "title": "Others",
            "value": "3"
          }
        ]
    
      };
      
      })
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="MyApp" ng-controller="myController" >
       <my-radiobutton options="radioGender" ng-model="genderValue"></my-radiobutton>
      <span>{{genderValue}}</span>
    </div>

    【讨论】:

    • 根据您的要求更改模板
    【解决方案2】:

    您应该在指令范围内使用“=”来绑定对象:

    directives.directive("dirname", function () {
         return {
             restrict: 'A',
             replace: false,
             scope: {
                 model: '=', // pass a referecne object
                 title: '@'  // path as string
             },
             controller: function ($scope, $rootScope) {
                 ...
             },
    
         }
     });
    
    
     <div dirname title="Menu Position" model="modelName" ></div>
    

    【讨论】:

      猜你喜欢
      • 2018-04-30
      • 1970-01-01
      • 2020-06-14
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 2019-11-19
      相关资源
      最近更新 更多