How to create an angularJs wrapper directive for a ui-bootstrap datepicker?
Solution 1:
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.
Plunker
Solution 2:
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.
Solution 3:
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.