Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

feat(datepicker): allow custom templates #4157

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions src/datepicker/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should note, this change would cause #1913 to be resolved.

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);
}
};
})
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -508,7 +511,9 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
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,
onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;
onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus,
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;

Expand Down Expand Up @@ -549,7 +554,8 @@ function ($compile, $parse, $document, $rootScope, $position, dateFilter, datePa
var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
popupEl.attr({
'ng-model': 'date',
'ng-change': 'dateSelection(date)'
'ng-change': 'dateSelection(date)',
'template-url': datepickerPopupTemplateUrl
});

function cameltoDash( string ){
Expand All @@ -558,6 +564,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"');
Expand Down Expand Up @@ -789,6 +797,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';
}
};
});
18 changes: 15 additions & 3 deletions src/datepicker/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ###
Expand Down Expand Up @@ -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`.
Expand Down
74 changes: 72 additions & 2 deletions src/datepicker/test/datepicker.spec.js
Original file line number Diff line number Diff line change
@@ -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'));
Expand Down Expand Up @@ -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_;
}));


Expand Down Expand Up @@ -352,6 +353,31 @@ describe('datepicker directive', function () {
expect(getTitle()).toBe('January 2014');
});

it('should support custom templates', function() {
$templateCache.put('foo/bar.html', '<div>baz</div>');

element = $compile('<datepicker ng-model="date" template-url="foo/bar.html"></datepicker>')($rootScope);
$rootScope.$digest();

expect(element.html()).toBe('baz');
});

it('should expose the controller in the template', function() {
$templateCache.put('template/datepicker/datepicker.html', '<div>{{datepicker.text}}</div>');

element = $compile('<datepicker ng-model="date"></datepicker>')($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 () {

Expand Down Expand Up @@ -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', '<div>baz</div>');

var elm = angular.element('<div><input ng-model="date" datepicker-popup datepicker-popup-template-url="foo/bar.html" is-open="true"></div>');

$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', '<div>baz</div>');

var elm = angular.element('<div><input ng-model="date" datepicker-popup datepicker-template-url="foo/bar.html" is-open="true"></div>');

$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();
Expand Down