17

I have created an angular directive for my jQuery UI datepicker. The problem is that the directive doesn't update the input's ng-model when a date is selected. Any idea why?

http://jsbin.com/ufoqan/1/edit

3 Answers 3

32

AngularJS actually provides a special controller for interacting with ngModel that you can use inside your directives; just add require: 'ngModel' to your directive definition.

This gives you a fourth paramter to your link function, which is the controller you asked for in require--in this case, an instance of ngModelController. It has a method called $setViewValue you can use to set the value of the model:

app.directive('datepicker', function() {
  return {
    require: 'ngModel',
    link: function(scope, el, attr, ngModel) {
      $(el).datepicker({
        onSelect: function(dateText) {
          scope.$apply(function() {
            ngModel.$setViewValue(dateText);
          });
        }
      });
    }
  };
});

The beautiful thing about ngModelController is it automatically takes care of validation and formatting (in the case of a specific input type) and integration with things like ngChange callbacks; check out this example: http://jsbin.com/ufoqan/6/edit

Sign up to request clarification or add additional context in comments.

1 Comment

Good answer. Note , there is an exisiting jquery UI datepicker here: github.com/angular-ui/ui-date Reading the source code will help understand how ngModelController works
6

There may be a better way, but this will work:

http://jsbin.com/ufoqan/4/edit

app.directive('datepicker', function() {
  return {
    link: function(scope, el, attr) {
      $(el).datepicker({
        onSelect: function(dateText) {
          console.log(dateText);
          var expression = attr.ngModel + " = " + "'" + dateText + "'";
          scope.$apply(expression);
          console.log(scope.startDate);
          // how do i set this elements model property ?
        }
      });
    }
  };
});

You also asked why. The reason is that jquery happens outside the angular system. You can find more info here under the $apply method: docs

2 Comments

thank you! what if i had a function call stored on my directive attribute and I wanted to invoke that. how would i do that? jsbin.com/ufoqan/5/edit
nvm, i think i got it, scope.$apply(attr.datepicker);
0

@Michelle Tilley and @Jonah are right about linking your directive to ngModel, but why you didn't use datePicker that is pure Angular instead of jQuery?
Well, i represent ADMdtp module. It's pure AngularJs dateTimePicker with lots of greate options:

  • completely synced with ngModel, so no need to destroy or manulay update dateTimePicker.
  • advance range picker; make as many dateTimePicker as you want related together, and again no need to destroy or manualy update each dateTimePicker.
  • disabing pattern; so easily you can disable any day(s) in week or month, like all weekends.
  • transition on changing days. (of curse you can disable it in options)
  • get full date details like date in UNIX format, Date format and year, month, day, hour and minute separately and ... by full-data attribute.
  • ...

<adm-dtp ng-model="date" full-data="date_full"></adm-dtp>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.