How to create an angularJs wrapper directive for a ui-bootstrap datepicker?
To be honest, I'm not quite sure why it's caused and what's causing your date to be "toString-ed" before showing it in the input.
However, I did find places to restructure your directive, and remove much unnecessary code, such as $compile
service, attributes changes, scope inheritance, require
in the directive, etc.. I used isolated scope, since I don't think every directive usage should know the parent scope as this might cause vicious bugs going forward. This is my changed directive:
angular.module('ui.bootstrap.demo').directive('myDatepicker', function() { return { restrict: 'A', scope: { model: "=", format: "@", options: "=datepickerOptions", myid: "@" }, templateUrl: 'datepicker-template.html', link: function(scope, element) { scope.popupOpen = false; scope.openPopup = function($event) { $event.preventDefault(); $event.stopPropagation(); scope.popupOpen = true; }; scope.open = function($event) { $event.preventDefault(); $event.stopPropagation(); scope.opened = true; }; } };});
And your HTML usage becomes:
<div my-datepicker model="container.two" datepicker-options="dateOptions" format="{{format}}" myid="myDP"></div>
Edit: Added the id
as a parameter to the directive. Plunker has been updated.
Your directive will work when you add these 2 lines to your directive definition:
return { priority: 1, terminal: true, ... }
This has to do with the order in which directives are executed.
So in your code
<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />
There are two directives: ngModel
and myDatepicker
. With priority you can make your own directive execute before ngModel does.
I think the answer from @omri-aharon is the best, but I'd like to point out some improvements that haven't been mentioned here:
Updated Plunkr
You can use the config to uniformly set your options such as the format and text options as follows:
angular.module('ui.bootstrap.demo', ['ui.bootstrap']).config(function (datepickerConfig, datepickerPopupConfig) { datepickerConfig.formatYear='yy'; datepickerConfig.startingDay = 1; datepickerConfig.showWeeks = false; datepickerPopupConfig.datepickerPopup = "shortDate"; datepickerPopupConfig.currentText = "Heute"; datepickerPopupConfig.clearText = "Löschen"; datepickerPopupConfig.closeText = "Schließen";});
I find this to be clearer and easier to update. This also allows you to vastly simplify the directive, template and markup.
Custom Directive
angular.module('ui.bootstrap.demo').directive('myDatepicker', function() { return { restrict: 'E', scope: { model: "=", myid: "@" }, templateUrl: 'datepicker-template.html', link: function(scope, element) { scope.popupOpen = false; scope.openPopup = function($event) { $event.preventDefault(); $event.stopPropagation(); scope.popupOpen = true; }; scope.open = function($event) { $event.preventDefault(); $event.stopPropagation(); scope.opened = true; }; } };});
Template
<div class="row"> <div class="col-md-6"> <p class="input-group"> <input type="text" class="form-control" id="{{myid}}" datepicker-popup ng-model="model" is-open="opened" ng-required="true" /> <span class="input-group-btn"> <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button> </span> </p> </div></div>
How to Use It
<my-datepicker model="some.model" myid="someid"></my-datepicker>
Further, if you want to enforce the use of a German locale formatting, you can add angular-locale_de.js. This ensures uniformity in the use of date constants like 'shortDate'
and forces the use of German month and day names.