15

I have a directive that is instantiated like this:

<datepicker ng-model="foo"></datepicker>

Inside the directive, the datepicker tag is replaced by this template:

template: '<div class="datepicker-wrapper input-append">' +
                     '<input type="text" class="datepicker" />' +
                     '<span class="add-on"><i class="icon-calendar"></i></span>' +
                   '</div>'

The value that I want ng-model bound to is the value of the input field. What is the best way to go about this so I maintain the two-way data binding of ng-model?

Dustin
  • 8,217
  • 11
  • 33
  • 44

2 Answers2

32

Depending on how complicated your passthrough is, you can just use the = scope to do a bidirectional bind between a local name and ngModel, like in this fiddle:

http://jsfiddle.net/mThrT/22/

I had a hell of a time setting up the fiddle for some reason (first time trying with angular) but here's the money shot:

template: '<div class="datepicker-wrapper input-append">' 
        + '<input type="text" class="datepicker" ng-model="bar" />' 
        + '<span class="add-on"><i class="icon-calendar"></i></span>' 
        + '</div>',
scope: {
    bar: '=ngModel'
},
jessegavin
  • 74,067
  • 28
  • 136
  • 164
Drew Miller
  • 675
  • 6
  • 15
  • THANK YOU!! Could not get this to work and had the dreaded No ngModel controller error... – malix Jul 01 '13 at 21:35
  • @malix - I suspect you have `require: 'ngModel'`. Remove the require part so your directive won't look for the `ngModelController`. – papar Apr 08 '15 at 11:00
10

There are a few ways to do this..

There is a function on the ctrl parameter of the linking function called .$setViewValue(valueHere) that you can use to set the value of whatever ngModel is referencing as well. It will do the work of setting things $dirty etc. There is also a property called .$viewValue you can use to get the current value. So you can set up a $watch on an isolate scope property to update the ngModel values.

The more correct way to do this would still be in the linking function, but it would look like so:

app.directive('myDirective', function() {
    restrict: 'E',
    require: 'ngModel',
    scope: {}, //isolate the scope
    template: '<div class="datepicker-wrapper input-append">' +
                         '<input type="text" class="datepicker" ng-model="date" />' +
                         '<span class="add-on"><i class="icon-calendar"></i></span>' +
                       '</div>',
    controller: function($scope) { 
    },
    link: function(scope, elem, attr, ctrl) {
       //get the value from ngModel
       scope.date = ctrl.$viewValue;

       //set the value of ngModel when the local date property changes
       scope.$watch('date', function(value) {
           if(ctrl.$viewValue != value) {
              ctrl.$setViewValue(value);
           }
       });
    }
});
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232
  • 1
    I am not having any success with this. I need to be able to set the ng-model on the datepicker tag independent of the directive so that someone consuming this directive can do something like and that model will be bound to the input field in the template. – Dustin Oct 22 '12 at 16:50
  • I did something similar with my own datepicker, but I also had the datepicker with its own controller managing its own models. – Oddman May 09 '13 at 22:41