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

Commit e58c42c

Browse files
committed
feat(datepicker): add datepickerOptions support
- Add support for options object to concisely configure datepicker Closes #5340
1 parent 61cdef1 commit e58c42c

File tree

3 files changed

+472
-48
lines changed

3 files changed

+472
-48
lines changed

src/datepicker/datepicker.js

+152-45
Original file line numberDiff line numberDiff line change
@@ -31,66 +31,172 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
3131
// Modes chain
3232
this.modes = ['day', 'month', 'year'];
3333

34-
// Interpolated configuration attributes
35-
angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle'], function(key) {
36-
self[key] = angular.isDefined($attrs[key]) ? $interpolate($attrs[key])($scope.$parent) : datepickerConfig[key];
37-
});
34+
if ($attrs.datepickerOptions) {
35+
angular.forEach([
36+
'formatDay',
37+
'formatDayHeader',
38+
'formatDayTitle',
39+
'formatMonth',
40+
'formatMonthTitle',
41+
'formatYear',
42+
'initDate',
43+
'maxDate',
44+
'maxMode',
45+
'minDate',
46+
'minMode',
47+
'showWeeks',
48+
'shortcutPropagation',
49+
'startingDay',
50+
'yearColumns',
51+
'yearRows'
52+
], function(key) {
53+
switch (key) {
54+
case 'formatDay':
55+
case 'formatDayHeader':
56+
case 'formatDayTitle':
57+
case 'formatMonth':
58+
case 'formatMonthTitle':
59+
case 'formatYear':
60+
self[key] = angular.isDefined($scope.datepickerOptions[key]) ? $interpolate($scope.datepickerOptions[key])($scope.$parent) : datepickerConfig[key];
61+
break;
62+
case 'showWeeks':
63+
case 'shortcutPropagation':
64+
case 'yearColumns':
65+
case 'yearRows':
66+
self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
67+
$scope.datepickerOptions[key] : datepickerConfig[key];
68+
break;
69+
case 'startingDay':
70+
if (angular.isDefined($scope.datepickerOptions.startingDay)) {
71+
self.startingDay = $scope.datepickerOptions.startingDay;
72+
} else if (angular.isNumber(datepickerConfig.startingDay)) {
73+
self.startingDay = datepickerConfig.startingDay;
74+
} else {
75+
self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
76+
}
3877

39-
// Evaled configuration attributes
40-
angular.forEach(['showWeeks', 'yearRows', 'yearColumns', 'shortcutPropagation'], function(key) {
41-
self[key] = angular.isDefined($attrs[key]) ?
42-
$scope.$parent.$eval($attrs[key]) : datepickerConfig[key];
43-
});
78+
break;
79+
case 'maxDate':
80+
case 'minDate':
81+
if ($scope.datepickerOptions[key]) {
82+
$scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
83+
if (value) {
84+
if (angular.isDate(value)) {
85+
self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
86+
} else {
87+
self[key] = new Date(dateFilter(value, 'medium'));
88+
}
89+
} else {
90+
self[key] = null;
91+
}
92+
93+
self.refreshView();
94+
});
95+
} else {
96+
self[key] = datepickerConfig[key] ? dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : null;
97+
}
4498

45-
if (angular.isDefined($attrs.startingDay)) {
46-
self.startingDay = $scope.$parent.$eval($attrs.startingDay);
47-
} else if (angular.isNumber(datepickerConfig.startingDay)) {
48-
self.startingDay = datepickerConfig.startingDay;
99+
break;
100+
case 'maxMode':
101+
case 'minMode':
102+
if ($scope.datepickerOptions[key]) {
103+
$scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) {
104+
self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key];
105+
if (key === 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) ||
106+
key === 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) {
107+
$scope.datepickerMode = self[key];
108+
}
109+
});
110+
} else {
111+
self[key] = $scope[key] = datepickerConfig[key] || null;
112+
}
113+
114+
break;
115+
case 'initDate':
116+
if ($scope.datepickerOptions.initDate) {
117+
this.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
118+
$scope.$watch(function() { return $scope.datepickerOptions.initDate; }, function(initDate) {
119+
if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
120+
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
121+
self.refreshView();
122+
}
123+
});
124+
} else {
125+
this.activeDate = new Date();
126+
}
127+
}
128+
});
49129
} else {
50-
self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
51-
}
130+
// Interpolated configuration attributes
131+
angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle'], function(key) {
132+
self[key] = angular.isDefined($attrs[key]) ? $interpolate($attrs[key])($scope.$parent) : datepickerConfig[key];
133+
});
52134

53-
// Watchable date attributes
54-
angular.forEach(['minDate', 'maxDate'], function(key) {
55-
if ($attrs[key]) {
56-
watchListeners.push($scope.$parent.$watch($attrs[key], function(value) {
57-
self[key] = value ? angular.isDate(value) ? dateParser.fromTimezone(new Date(value), ngModelOptions.timezone) : new Date(dateFilter(value, 'medium')) : null;
58-
self.refreshView();
59-
}));
135+
// Evaled configuration attributes
136+
angular.forEach(['showWeeks', 'yearRows', 'yearColumns', 'shortcutPropagation'], function(key) {
137+
self[key] = angular.isDefined($attrs[key]) ?
138+
$scope.$parent.$eval($attrs[key]) : datepickerConfig[key];
139+
});
140+
141+
if (angular.isDefined($attrs.startingDay)) {
142+
self.startingDay = $scope.$parent.$eval($attrs.startingDay);
143+
} else if (angular.isNumber(datepickerConfig.startingDay)) {
144+
self.startingDay = datepickerConfig.startingDay;
60145
} else {
61-
self[key] = datepickerConfig[key] ? dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : null;
146+
self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
62147
}
63-
});
64148

65-
angular.forEach(['minMode', 'maxMode'], function(key) {
66-
if ($attrs[key]) {
67-
watchListeners.push($scope.$parent.$watch($attrs[key], function(value) {
68-
self[key] = $scope[key] = angular.isDefined(value) ? value : $attrs[key];
69-
if (key === 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) ||
70-
key === 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) {
71-
$scope.datepickerMode = self[key];
149+
// Watchable date attributes
150+
angular.forEach(['minDate', 'maxDate'], function(key) {
151+
if ($attrs[key]) {
152+
watchListeners.push($scope.$parent.$watch($attrs[key], function(value) {
153+
if (value) {
154+
if (angular.isDate(value)) {
155+
self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone);
156+
} else {
157+
self[key] = new Date(dateFilter(value, 'medium'));
158+
}
159+
} else {
160+
self[key] = null;
161+
}
162+
163+
self.refreshView();
164+
}));
165+
} else {
166+
self[key] = datepickerConfig[key] ? dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : null;
167+
}
168+
});
169+
170+
angular.forEach(['minMode', 'maxMode'], function(key) {
171+
if ($attrs[key]) {
172+
watchListeners.push($scope.$parent.$watch($attrs[key], function(value) {
173+
self[key] = $scope[key] = angular.isDefined(value) ? value : $attrs[key];
174+
if (key === 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) ||
175+
key === 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) {
176+
$scope.datepickerMode = self[key];
177+
}
178+
}));
179+
} else {
180+
self[key] = $scope[key] = datepickerConfig[key] || null;
181+
}
182+
});
183+
184+
if (angular.isDefined($attrs.initDate)) {
185+
this.activeDate = dateParser.fromTimezone($scope.$parent.$eval($attrs.initDate), ngModelOptions.timezone) || new Date();
186+
watchListeners.push($scope.$parent.$watch($attrs.initDate, function(initDate) {
187+
if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
188+
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
189+
self.refreshView();
72190
}
73191
}));
74192
} else {
75-
self[key] = $scope[key] = datepickerConfig[key] || null;
193+
this.activeDate = new Date();
76194
}
77-
});
195+
}
78196

79197
$scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;
80198
$scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
81199

82-
if (angular.isDefined($attrs.initDate)) {
83-
this.activeDate = dateParser.fromTimezone($scope.$parent.$eval($attrs.initDate), ngModelOptions.timezone) || new Date();
84-
watchListeners.push($scope.$parent.$watch($attrs.initDate, function(initDate) {
85-
if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {
86-
self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone);
87-
self.refreshView();
88-
}
89-
}));
90-
} else {
91-
this.activeDate = new Date();
92-
}
93-
94200
$scope.disabled = angular.isDefined($attrs.disabled) || false;
95201
if (angular.isDefined($attrs.ngDisabled)) {
96202
watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) {
@@ -501,6 +607,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
501607
},
502608
scope: {
503609
datepickerMode: '=?',
610+
datepickerOptions: '=?',
504611
dateDisabled: '&',
505612
customClass: '&',
506613
shortcutPropagation: '&?'

src/datepicker/docs/readme.md

+23
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,29 @@ The datepicker has 3 modes:
2727
_(Default: `day`)_ -
2828
Current mode of the datepicker _(day|month|year)_. Can be used to initialize the datepicker in a specific mode.
2929

30+
* `datepicker-options`
31+
<small class="badge">$</small> -
32+
An optional object to configure the datepicker in one place. If this attribute is used, all supported options must be specified instead of the attributes.
33+
34+
The supported options are:
35+
36+
- formatDay
37+
- formatDayHeader
38+
- formatDayTitle
39+
- formatMonth
40+
- formatMonthTitle
41+
- formatYear
42+
- initDate
43+
- maxDate
44+
- maxMode
45+
- minDate
46+
- minMode
47+
- shortcutPropagation
48+
- showWeeks
49+
- startingDay
50+
- yearColumns
51+
- yearRows
52+
3053
* `format-day`
3154
<small class="badge">C</small>
3255
_(Default: `dd`)_ -

0 commit comments

Comments
 (0)