diff --git a/src/datepicker/datepicker.js b/src/datepicker/datepicker.js
index 5bdb8f7451..e1e62c6f16 100644
--- a/src/datepicker/datepicker.js
+++ b/src/datepicker/datepicker.js
@@ -225,21 +225,22 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
return {
restrict: 'EA',
replace: true,
- templateUrl: 'template/datepicker/datepicker.html',
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'template/datepicker/datepicker.html';
+ },
scope: {
datepickerMode: '=?',
dateDisabled: '&',
customClass: '&',
shortcutPropagation: '&?'
},
- require: ['datepicker', '?^ngModel'],
+ require: ['datepicker', '^ngModel'],
controller: 'DatepickerController',
+ controllerAs: 'datepicker',
link: function(scope, element, attrs, ctrls) {
var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];
- if ( ngModelCtrl ) {
- datepickerCtrl.init( ngModelCtrl );
- }
+ datepickerCtrl.init(ngModelCtrl);
}
};
})
@@ -477,6 +478,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
.constant('datepickerPopupConfig', {
datepickerPopup: 'yyyy-MM-dd',
+ datepickerPopupTemplateUrl: 'template/datepicker/popup.html',
+ datepickerTemplateUrl: 'template/datepicker/datepicker.html',
html5Types: {
date: 'yyyy-MM-dd',
'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',
@@ -506,7 +509,9 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
link: function(scope, element, attrs, ngModel) {
var dateFormat,
closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,
- appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;
+ appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody,
+ datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl,
+ datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;
scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;
@@ -547,7 +552,8 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
var popupEl = angular.element('
');
popupEl.attr({
'ng-model': 'date',
- 'ng-change': 'dateSelection(date)'
+ 'ng-change': 'dateSelection(date)',
+ 'template-url': datepickerPopupTemplateUrl
});
function cameltoDash( string ){
@@ -556,6 +562,8 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
// datepicker element
var datepickerEl = angular.element(popupEl.children()[0]);
+ datepickerEl.attr('template-url', datepickerTemplateUrl);
+
if (isHtml5DateInput) {
if (attrs.type == 'month') {
datepickerEl.attr('datepicker-mode', '"month"');
@@ -785,6 +793,8 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
restrict:'EA',
replace: true,
transclude: true,
- templateUrl: 'template/datepicker/popup.html'
+ templateUrl: function(element, attrs) {
+ return attrs.templateUrl || 'template/datepicker/popup.html';
+ }
};
});
diff --git a/src/datepicker/docs/readme.md b/src/datepicker/docs/readme.md
index 0311b0596f..ecb665fb6f 100644
--- a/src/datepicker/docs/readme.md
+++ b/src/datepicker/docs/readme.md
@@ -80,10 +80,14 @@ All settings can be provided as attributes in the `datepicker` or globally confi
* `year-range`
_(Default: 20)_ :
Number of years displayed in year selection.
-
+
* `shortcut-propagation`
- _(Default: false)_ :
- An option to disable or enable shortcut's event propagation.
+ _(Default: false)_ :
+ An option to disable or enable shortcut's event propagation.
+
+ * `template-url`
+ _(Default: 'template/datepicker/datepicker.html') :
+ Allows overriding of default template of the datepicker
### Popup Settings ###
@@ -115,6 +119,14 @@ Specific settings for the `datepicker-popup`, that can globally configured throu
_(Default: true)_ :
Whether to close calendar when a date is chosen.
+ * `datepicker-popup-template-url`
+ _(Default: 'template/datepicker/popup.html') :
+ Allows overriding of default template of the popup
+
+ * `datepicker-template-url`
+ _(Default: 'template/datepicker/popup.html') :
+ Allows overriding of default template of the datepicker used in popup
+
* `datepicker-append-to-body`
_(Default: false)_:
Append the datepicker popup element to `body`, rather than inserting after `datepicker-popup`. For global configuration, use `datepickerPopupConfig.appendToBody`.
diff --git a/src/datepicker/test/datepicker.spec.js b/src/datepicker/test/datepicker.spec.js
index c0342a8710..90602b3a4c 100644
--- a/src/datepicker/test/datepicker.spec.js
+++ b/src/datepicker/test/datepicker.spec.js
@@ -1,5 +1,5 @@
describe('datepicker directive', function () {
- var $rootScope, $compile, element;
+ var $rootScope, $compile, $templateCache, element;
beforeEach(module('ui.bootstrap.datepicker'));
beforeEach(module('template/datepicker/datepicker.html'));
beforeEach(module('template/datepicker/day.html'));
@@ -198,10 +198,11 @@ describe('datepicker directive', function () {
});
describe('', function () {
- beforeEach(inject(function(_$compile_, _$rootScope_) {
+ beforeEach(inject(function(_$compile_, _$rootScope_, _$templateCache_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$rootScope.date = new Date('September 30, 2010 15:30:00');
+ $templateCache = _$templateCache_;
}));
@@ -352,6 +353,31 @@ describe('datepicker directive', function () {
expect(getTitle()).toBe('January 2014');
});
+ it('should support custom templates', function() {
+ $templateCache.put('foo/bar.html', 'baz
');
+
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+
+ expect(element.html()).toBe('baz');
+ });
+
+ it('should expose the controller in the template', function() {
+ $templateCache.put('template/datepicker/datepicker.html', '{{datepicker.text}}
');
+
+ element = $compile('')($rootScope);
+ $rootScope.$digest();
+
+ var ctrl = element.controller('datepicker');
+ expect(ctrl).toBeDefined();
+ expect(element.html()).toBe('');
+
+ ctrl.text = 'baz';
+ $rootScope.$digest();
+
+ expect(element.html()).toBe('baz');
+ });
+
// issue #3079
describe('time zone bug', function () {
@@ -2007,6 +2033,50 @@ describe('datepicker directive', function () {
});
});
+ describe('with datepicker-popup-template-url', function() {
+ beforeEach(function() {
+ $rootScope.date = new Date();
+ });
+
+ afterEach(function () {
+ $document.find('body').find('.dropdown-menu').remove();
+ });
+
+ it('should allow custom templates for the popup', function() {
+ $templateCache.put('foo/bar.html', 'baz
');
+
+ var elm = angular.element('');
+
+ $compile(elm)($rootScope);
+ $rootScope.$digest();
+
+ expect(elm.children().eq(1).html()).toBe('baz');
+ });
+ });
+
+ describe('with datepicker-template-url', function() {
+ beforeEach(function() {
+ $rootScope.date = new Date();
+ });
+
+ afterEach(function () {
+ $document.find('body').find('.dropdown-menu').remove();
+ });
+
+ it('should allow custom templates for the datepicker', function() {
+ $templateCache.put('foo/bar.html', 'baz
');
+
+ var elm = angular.element('');
+
+ $compile(elm)($rootScope);
+ $rootScope.$digest();
+
+ var datepicker = elm.find('[datepicker]');
+
+ expect(datepicker.html()).toBe('baz');
+ });
+ });
+
describe('with an append-to-body attribute', function() {
beforeEach(function() {
$rootScope.date = new Date();