Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ng-model within a directive

Tags:

angularjs

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.

like image 996
Mike Avatar asked Oct 03 '12 22:10

Mike


People also ask

What is [( ngModel )]?

[(ngModel)]="overRideRate" is the short form of [ngModel]="overRideRate" (ngModelChange)="overRideRate = $event" [ngModel]="overRideRate" is to bind overRideRate to the input.value. (ngModelChange)="overRideRate = $event" is to update overRideRate with the value of input. value when the change event was emitted.

Can we use ngModel and formControlName together?

In short ngModel can't be used by itself within FormGroup When you use formControlName, ngModel does not activate or create a control (it's simply used as an @Input). formControlName just links to the existing input you created in your class.

Can we use ngModel in input tag?

The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.


1 Answers

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)
      }
    }
  })
like image 187
Mike Avatar answered Oct 01 '22 15:10

Mike