Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit a090079

Browse files
crisbetojelbourn
authored andcommitted
feat(datepicker): allow the date locale to be overwritten on a per element basis (#9749)
Adds the `md-date-locale` attribute which can be used to overwrite the locale formatting on a per-element basis. This wasn't possible before, because the locale was global and it was being applied during the `config` phase. These changes relate to PR #9736, because the specific datepicker modes might require special formatting (e.g. only showing the MM/YY on a credit card form). Fixes #9270.
1 parent b7ae33e commit a090079

File tree

2 files changed

+40
-13
lines changed

2 files changed

+40
-13
lines changed

src/components/datepicker/js/datepickerDirective.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* @param {expression=} ng-change Expression evaluated when the model value changes.
2525
* @param {expression=} ng-focus Expression evaluated when the input is focused or the calendar is opened.
2626
* @param {expression=} ng-blur Expression evaluated when focus is removed from the input or the calendar is closed.
27+
* @param {boolean=} ng-disabled Whether the datepicker is disabled.
28+
* @param {boolean=} ng-required Whether a value is required for the datepicker.
2729
* @param {Date=} md-min-date Expression representing a min date (inclusive).
2830
* @param {Date=} md-max-date Expression representing a max date (inclusive).
2931
* @param {(function(Date): boolean)=} md-date-filter Function expecting a date and returning a boolean whether it can be selected or not.
@@ -36,8 +38,9 @@
3638
* * `"all"` - Hides all icons.
3739
* * `"calendar"` - Only hides the calendar icon.
3840
* * `"triangle"` - Only hides the triangle icon.
39-
* @param {boolean=} ng-disabled Whether the datepicker is disabled.
40-
* @param {boolean=} ng-required Whether a value is required for the datepicker.
41+
* @param {Object=} md-date-locale Allows for the values from the `$mdDateLocaleProvider` to be
42+
* ovewritten on a per-element basis (e.g. `msgOpenCalendar` can be overwritten with
43+
* `md-date-locale="{ msgOpenCalendar: 'Open a special calendar' }"`).
4144
*
4245
* @description
4346
* `<md-datepicker>` is a component used to select a single date.
@@ -79,7 +82,7 @@
7982
'<md-button type="button" md-no-ink ' +
8083
'class="md-datepicker-triangle-button md-icon-button" ' +
8184
'ng-click="ctrl.openCalendarPane($event)" ' +
82-
'aria-label="{{::ctrl.dateLocale.msgOpenCalendar}}">' +
85+
'aria-label="{{::ctrl.locale.msgOpenCalendar}}">' +
8386
'<div class="md-datepicker-expand-triangle"></div>' +
8487
'</md-button>';
8588

@@ -102,7 +105,7 @@
102105
'<div class="md-datepicker-input-mask-opaque"></div>' +
103106
'</div>' +
104107
'<div class="md-datepicker-calendar">' +
105-
'<md-calendar role="dialog" aria-label="{{::ctrl.dateLocale.msgCalendar}}" ' +
108+
'<md-calendar role="dialog" aria-label="{{::ctrl.locale.msgCalendar}}" ' +
106109
'md-current-view="{{::ctrl.currentView}}"' +
107110
'md-min-date="ctrl.minDate"' +
108111
'md-max-date="ctrl.maxDate"' +
@@ -120,7 +123,8 @@
120123
currentView: '@mdCurrentView',
121124
dateFilter: '=mdDateFilter',
122125
isOpen: '=?mdIsOpen',
123-
debounceInterval: '=mdDebounceInterval'
126+
debounceInterval: '=mdDebounceInterval',
127+
dateLocale: '=mdDateLocale'
124128
},
125129
controller: DatePickerCtrl,
126130
controllerAs: 'ctrl',
@@ -232,9 +236,6 @@
232236
/** @final */
233237
this.$window = $window;
234238

235-
/** @final */
236-
this.dateLocale = $mdDateLocale;
237-
238239
/** @final */
239240
this.dateUtil = $$mdDateUtil;
240241

@@ -247,6 +248,13 @@
247248
/** @final */
248249
this.$$rAF = $$rAF;
249250

251+
/**
252+
* Holds locale-specific formatters, parsers, labels etc. Allows
253+
* the user to override specific ones from the $mdDateLocale provider.
254+
* @type {!Object}
255+
*/
256+
this.locale = this.dateLocale ? angular.extend({}, $mdDateLocale, this.dateLocale) : $mdDateLocale;
257+
250258
/**
251259
* The root document element. This is used for attaching a top-level click handler to
252260
* close the calendar panel when a click outside said panel occurs. We use `documentElement`
@@ -585,14 +593,14 @@
585593
*/
586594
DatePickerCtrl.prototype.handleInputEvent = function() {
587595
var inputString = this.inputElement.value;
588-
var parsedDate = inputString ? this.dateLocale.parseDate(inputString) : null;
596+
var parsedDate = inputString ? this.locale.parseDate(inputString) : null;
589597
this.dateUtil.setDateTimeToMidnight(parsedDate);
590598

591599
// An input string is valid if it is either empty (representing no date)
592600
// or if it parses to a valid date that the user is allowed to select.
593601
var isValidInput = inputString == '' || (
594602
this.dateUtil.isValidDate(parsedDate) &&
595-
this.dateLocale.isDateComplete(inputString) &&
603+
this.locale.isDateComplete(inputString) &&
596604
this.isDateEnabled(parsedDate)
597605
);
598606

@@ -869,7 +877,7 @@
869877
var timezone = this.$mdUtil.getModelOption(this.ngModelCtrl, 'timezone');
870878

871879
this.date = value;
872-
this.inputElement.value = this.dateLocale.formatDate(value, timezone);
880+
this.inputElement.value = this.locale.formatDate(value, timezone);
873881
this.mdInputContainer && this.mdInputContainer.setHasValue(!!value);
874882
this.closeCalendarPane();
875883
this.resizeInputElement();

src/components/datepicker/js/datepickerDirective.spec.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,31 @@ describe('md-datepicker', function() {
129129
});
130130

131131
it('should pass the timezone to the formatting function', function() {
132-
spyOn(dateLocale, 'formatDate');
132+
spyOn(controller.locale, 'formatDate');
133133

134134
createDatepickerInstance('<md-datepicker ng-model="myDate" ' +
135135
'ng-model-options="{ timezone: \'utc\' }"></md-datepicker>');
136136

137-
expect(dateLocale.formatDate).toHaveBeenCalledWith(pageScope.myDate, 'utc');
137+
expect(controller.locale.formatDate).toHaveBeenCalledWith(pageScope.myDate, 'utc');
138+
});
139+
140+
it('should allow for the locale to be overwritten on a specific element', function() {
141+
pageScope.myDate = new Date(2015, SEP, 1);
142+
143+
pageScope.customLocale = {
144+
formatDate: function() {
145+
return 'September First';
146+
}
147+
};
148+
149+
spyOn(pageScope.customLocale, 'formatDate').and.callThrough();
150+
151+
createDatepickerInstance(
152+
'<md-datepicker ng-model="myDate" md-date-locale="customLocale"></md-datepicker>'
153+
);
154+
155+
expect(pageScope.customLocale.formatDate).toHaveBeenCalled();
156+
expect(ngElement.find('input').val()).toBe('September First');
138157
});
139158

140159
describe('ngMessages support', function() {

0 commit comments

Comments
 (0)