在指令中使用ng-model

6
我在AngularJS中定义了一个自定义指令。基本上我想要的是用户从选择框中选择一个值,然后将该值附加到数组中。这会导致调用我的自定义指令并在屏幕上呈现一个新元素。我希望该指令生成的文本字段绑定到控制器的属性。
HTML
<device-list ng-repeat="device in devices" key="device.key" display-name="device.display_name" bind-prefix="descriptions"></device-list>

指令

angular.module('device_list_tag', []).
  directive('deviceList', function() {
    return {
      restrict: 'E',
      require: '?ngModel',
      scope: {
        devices: '=',
        key: '=',
        displayName: '=',
        bindPrefix: '@'
      },
      link: function(scope, element, attrs) {

        var deviceListElement = $(element)
        var containerDiv = $('<div>')
          .addClass('row')


        var labelTag = $('<label>').text(scope.displayName)
          .addClass('span1')

        var bindField = attrs.bindPrefix+'.'+scope.key

        var textField = $('<input>')
          .addClass('span3')
          .attr('ng-model', bindField)

        containerDiv.append(labelTag)
        containerDiv.append(textField)

        deviceListElement.append(containerDiv)
      }
    }
  })

控制器

function DevicesCtrl($scope) {
  descriptions = {}
}

似乎ng-model只适用于指令的作用域,我该如何使其适用于父级?如果页面上有一堆文本字段,例如:

<input ng-model="descriptions.test"/>

除了由选择框生成的字段之外,它完全有效。

4个回答

9

好的,我弄清楚了。这涉及到将我的父属性作为“=”传递(由Tosh建议)。我还必须调用$compile使其识别ng-model指令。以下是完整的代码,我相信有一种更干净的方法来做到这一点,但我很高兴它能正常工作。

angular.module('device_list_tag', []).
  directive('deviceList', function($compile) {
    return {
      restrict: 'E',
      scope: {
        devices: '=',
        key: '=',
        displayName: '=',
        bindAttr: '=' // added
      },
      link: function(scope, element, attrs) {

        console.log(scope)

        var deviceListElement = $(element)
        var containerDiv = $('<div>')
          .addClass('row')


        var labelTag = $('<label>').text(scope.displayName)
          .addClass('span1')

        var bindField = 'bindAttr.'+scope.key

        var textField = $('<input>')
          .addClass('span3')
          .attr('ng-model', bindField)

        $compile(textField)(scope) // added

        containerDiv.append(labelTag)
        containerDiv.append(textField)

        deviceListElement.append(containerDiv)
      }
    }
  })

你为什么不在指令中使用模板属性,并像往常一样绑定对象?例如:template: '<input ng-model="bindAttr" />...'这不是模板的作用吗?或者我理解错了吗?就像页面底部的例子:http://docs.angularjs.org/guide/directive - F Lekschas
问题在于我不知道从指令内部绑定到的属性的名称。我尝试使用模板,但遇到的问题是如何使{{some.random.attribute}}起作用。 - Mike
我会绑定一个固定的变量,一旦我弄清楚了some.random.attribute的值,就只需更新该变量的值。例如,您可以设置一个名为getSomeRandomAttr(key)的函数,该函数连接到您父级的作用域或调用服务器。然后,在调用该函数后,您只需要更新固定变量即可。 - F Lekschas
1
请您能否将可用的<device-list..指令的HTML部分发布出来,以便我们了解。 - Rajkamal Subramanian
我相信最终的HTML代码是:<device-list ng-repeat="device in devices" key="device.key" display-name="device.display_name" bind-attr="descriptions"></device-list> - nrw

2
也许你可以在指令定义中添加bindField: '='。并使用这个变量连接到父作用域。

我现在正在尝试,但是还没有找到如何将变量“绑定”到文本字段的方法。你有什么建议吗? - Mike

1
你是在询问:
1)在我们编辑隔离作用域表单元素的同时,保持父作用域数组更新。如果是这样,我已经在这个jsfiddle http://jsfiddle.net/W7YrZ/2/ 中复制了一个类似的场景。
我试图做什么的总结:
1)在ng-repeat中分配一个属性“umbilical”,并将其与当前迭代项一起使用。
2)然后,在父作用域上下文中在链接函数中评估此属性,这为父作用域数组中的一个对象提供了引用(指针)在这里,即“profiles”。
3)然后,正如@Mark Rajcok所说,“基元按值复制,而对象按引用复制”。我将通过步骤2获得的对象绑定到模板字符串中的文本框中。

这对我来说非常有效,也是我缺失的关键(在我的情况下,我正在编写一个日期范围指令,并且一直在努力将ng-model映射到开始和结束范围变量)。 - jadrake

-3

出于对Angular中jQuery代码的清洁性和JavaScript验证的考虑,只需将选择器$替换为angular.element

$('<input>').addClass('span3')

必须编写

angular.element('<input>').addClass('span3')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接