Using ng-model within a directive

2020-07-10 10:57发布

I've got a custom defined directive in angularjs. Basically what I want to happen is the user will pick a value from a select box and that will append a value to an array. This causes my custom directive to be invoked and render a new element on the screen. I want the text field that the directive generates to bind to the controller's attribute.

Html

<device-list ng-repeat="device in devices" key="device.key" display-name="device.display_name" bind-prefix="descriptions"></device-list>

Directive

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)
      }
    }
  })

Controller

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

It appears as though as ng-model is local to the directive's scope, how do I make it apply to the parent? If I have a bunch of text fields on the page like

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

It works works except with the fields generated by the select box.

标签: angularjs
4条回答
兄弟一词,经得起流年.
2楼-- · 2020-07-10 11:01

Ok, I figured it out. It involved passing in my parent attribute as '=' (suggested by Tosh). I also had to make a call to $compile to make it recognize the ng-model directive. Here's the full code, I'm sure there's a way to do this cleaner but I'm just glad to have it working.

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)
      }
    }
  })
查看更多
▲ chillily
3楼-- · 2020-07-10 11:01

for reasons of cleanliness of jQuery code in angular and for validation javascript, just replace the selector $ in angular.element

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

must be written

angular.element('<input>').addClass('span3')
查看更多
Root(大扎)
4楼-- · 2020-07-10 11:06

Are you asking for,

1) Keep the parent scope array updated, while we edit the isolate scope form elements. If yes, i have replicated a similar scenario in this fiddle http://jsfiddle.net/W7YrZ/2/.

Summary of what i was trying to do.

1) Assign a attribute umbilical in the ng-repeat with the current item of the iteration.

2) Then im evaluating this attribute inside the linking function in the context of the parent scope, which gives a reference(pointer) to one of the array object in the parent scope array here profiles.

3)Then as @Mark Rajcok says "primitives are copied by value, while objects are copied by reference". I'm binding that object got through step 2 to the text boxes in the template string.

查看更多
对你真心纯属浪费
5楼-- · 2020-07-10 11:15

May be you can add bindField: '=' in your scope directive definition. And use this variable to connect to the parent scope.

查看更多
登录 后发表回答