@vaadin/vaadin-date-picker 4.4.5 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,13 +97,14 @@ To use the Material theme, import the correspondent file from the `theme/materia
97
97
 
98
98
  1. Fork the `vaadin-date-picker` repository and clone it locally.
99
99
 
100
- 1. Make sure you have [npm](https://www.npmjs.com/) and [Bower](https://bower.io) installed.
100
+ 2. Make sure you have [npm](https://www.npmjs.com/) and [Bower](https://bower.io)
101
+ and [Polymer](https://polymer-library.polymer-project.org/) installed.
101
102
 
102
- 1. When in the `vaadin-date-picker` directory, run `npm install` and then `bower install` to install dependencies.
103
+ 3. When in the `vaadin-date-picker` directory, run `npm install` and then `bower install` to install dependencies.
103
104
 
104
- 1. Run `npm start`, browser will automatically open the component API documentation.
105
+ 4. Run `npm start`, browser will automatically open the component API documentation.
105
106
 
106
- 1. You can also open demo or in-browser tests by adding **demo** or **test** to the URL, for example:
107
+ 5. You can also open demo or in-browser tests by adding **demo** or **test** to the URL, for example:
107
108
 
108
109
  - http://127.0.0.1:3000/components/vaadin-date-picker/demo
109
110
  - http://127.0.0.1:3000/components/vaadin-date-picker/test
@@ -111,8 +112,8 @@ To use the Material theme, import the correspondent file from the `theme/materia
111
112
 
112
113
  ## Running tests from the command line
113
114
 
114
- 1. When in the `vaadin-date-picker` directory, run `polymer test`
115
-
115
+ 1. When in the `vaadin-date-picker` directory, run `npm test` (this will execute:"test": "wct")
116
+ (tests will be fetched from the `test/basics.html` file)
116
117
 
117
118
  ## Following the coding style
118
119
 
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "repository": "vaadin/vaadin-date-picker",
11
11
  "homepage": "https://vaadin.com/components",
12
12
  "name": "@vaadin/vaadin-date-picker",
13
- "version": "4.4.5",
13
+ "version": "4.6.0",
14
14
  "main": "vaadin-date-picker.js",
15
15
  "author": "Vaadin Ltd",
16
16
  "license": "Apache-2.0",
@@ -37,7 +37,7 @@
37
37
  "@polymer/iron-resizable-behavior": "^3.0.0",
38
38
  "@polymer/polymer": "^3.0.0",
39
39
  "@vaadin/vaadin-button": "^2.4.0",
40
- "@vaadin/vaadin-text-field": "^2.8.0",
40
+ "@vaadin/vaadin-text-field": "^2.10.0",
41
41
  "@vaadin/vaadin-themable-mixin": "^1.6.1",
42
42
  "@vaadin/vaadin-control-state-mixin": "^2.2.2",
43
43
  "@vaadin/vaadin-overlay": "^3.5.0",
@@ -37,6 +37,53 @@ export const DatePickerHelper = class VaadinDatePickerHelper {
37
37
  return Math.floor((daysSinceFirstOfJanuary) / 7 + 1);
38
38
  }
39
39
 
40
+ /**
41
+ * Calculate the year of the date based on the provided reference date.
42
+ * Gets a two-digit year and returns a full year.
43
+ * @param {!Date} referenceDate The date to act as basis in the calculation
44
+ * @param {!number} year Should be in the range of [0, 99]
45
+ * @param {number} month
46
+ * @param {number} day
47
+ * @return {!number} Adjusted year value
48
+ */
49
+ static _getAdjustedYear(referenceDate, year, month = 0, day = 1) {
50
+ if (year > 99) {
51
+ throw new Error('The provided year cannot have more than 2 digits.');
52
+ }
53
+ if (year < 0) {
54
+ throw new Error('The provided year cannot be negative.');
55
+ }
56
+ // Year values up to 2 digits are parsed based on the reference date.
57
+ let adjustedYear = year + Math.floor(referenceDate.getFullYear() / 100) * 100;
58
+ if (referenceDate < new Date(adjustedYear - 50, month, day)) {
59
+ adjustedYear -= 100;
60
+ } else if (referenceDate > new Date(adjustedYear + 50, month, day)) {
61
+ adjustedYear += 100;
62
+ }
63
+ return adjustedYear;
64
+ }
65
+
66
+ /**
67
+ * Parse date string of one of the following date formats:
68
+ * - ISO 8601 `"YYYY-MM-DD"`
69
+ * - 6-digit extended ISO 8601 `"+YYYYYY-MM-DD"`, `"-YYYYYY-MM-DD"`
70
+ * @param {!string} str Date string to parse
71
+ * @return {Date} Parsed date
72
+ */
73
+ static _parseDate(str) {
74
+ // Parsing with RegExp to ensure correct format
75
+ var parts = /^([-+]\d{1}|\d{2,4}|[-+]\d{6})-(\d{1,2})-(\d{1,2})$/.exec(str);
76
+ if (!parts) {
77
+ return;
78
+ }
79
+
80
+ var date = new Date(0, 0); // Wrong date (1900-01-01), but with midnight in local time
81
+ date.setFullYear(parseInt(parts[1], 10));
82
+ date.setMonth(parseInt(parts[2], 10) - 1);
83
+ date.setDate(parseInt(parts[3], 10));
84
+ return date;
85
+ }
86
+
40
87
  /**
41
88
  * Check if two dates are equal.
42
89
  *
@@ -72,8 +72,14 @@ declare class DatePickerLightElement extends
72
72
  ThemableMixin(
73
73
  DatePickerMixin(
74
74
  PolymerElement)) {
75
+
76
+ /**
77
+ * The method is overridden to allow the customization of
78
+ * the input element value property name, which can be
79
+ * achieved by providing a custom `attrForValue` property.
80
+ */
81
+ readonly _inputElementValueProperty: string;
75
82
  _overlayInitialized: boolean;
76
- _inputValue: string|undefined;
77
83
 
78
84
  /**
79
85
  * Name of the two-way data-bindable property representing the
@@ -130,15 +130,17 @@ class DatePickerLightElement extends
130
130
  return this.querySelector('vaadin-text-field,iron-input,paper-input,.paper-input-input,.input');
131
131
  }
132
132
 
133
- set _inputValue(value) {
134
- if (this._inputElement) {
135
- this._inputElement[dashToCamelCase(this.attrForValue)] = value;
136
- }
137
- }
138
-
139
- /** @return {string | undefined} */
140
- get _inputValue() {
141
- return this._inputElement && this._inputElement[dashToCamelCase(this.attrForValue)];
133
+ /**
134
+ * The method is overridden to allow the customization of
135
+ * the input element value property name, which can be
136
+ * achieved by providing a custom `attrForValue` property.
137
+ *
138
+ * @protected
139
+ * @override
140
+ * @return {string}
141
+ */
142
+ get _inputElementValueProperty() {
143
+ return dashToCamelCase(this.attrForValue);
142
144
  }
143
145
  }
144
146
 
@@ -33,6 +33,18 @@ export {DatePickerMixinConstructor};
33
33
  interface DatePickerMixin {
34
34
  readonly _inputElement: HTMLElement|null;
35
35
 
36
+ /**
37
+ * A property for accessing the input element's value.
38
+ *
39
+ * Override this getter if the property is different from the default `value` one.
40
+ */
41
+ readonly _inputElementValueProperty: string;
42
+
43
+ /**
44
+ * The input element's value.
45
+ */
46
+ _inputElementValue: string;
47
+
36
48
  /**
37
49
  * The current selected date.
38
50
  */
@@ -141,12 +153,22 @@ interface DatePickerMixin {
141
153
  * // Translation of the Cancel button text.
142
154
  * cancel: 'Cancel',
143
155
  *
156
+ * // Used for adjusting the year value when parsing dates with short years.
157
+ * // The year values between 0 and 99 are evaluated and adjusted.
158
+ * // Example: for a referenceDate of 1970-10-30;
159
+ * // dateToBeParsed: 40-10-30, result: 1940-10-30
160
+ * // dateToBeParsed: 80-10-30, result: 1980-10-30
161
+ * // dateToBeParsed: 10-10-30, result: 2010-10-30
162
+ * // Supported date format: ISO 8601 `"YYYY-MM-DD"` (default)
163
+ * // The default value is the current date.
164
+ * referenceDate: '',
165
+ *
144
166
  * // A function to format given `Object` as
145
167
  * // date string. Object is in the format `{ day: ..., month: ..., year: ... }`
146
168
  * // Note: The argument month is 0-based. This means that January = 0 and December = 11.
147
- * formatDate: d => {
148
- * // returns a string representation of the given
149
- * // object in 'MM/DD/YYYY' -format
169
+ * formatDate(d) {
170
+ * const yearStr = String(d.year).replace(/\d+/, (y) => '0000'.substr(y.length) + y);
171
+ * return [d.month + 1, d.day, yearStr].join('/');
150
172
  * },
151
173
  *
152
174
  * // A function to parse the given text to an `Object` in the format `{ day: ..., month: ..., year: ... }`.
@@ -194,6 +216,14 @@ interface DatePickerMixin {
194
216
  * The latest date that can be selected. All later dates will be disabled.
195
217
  */
196
218
  _maxDate: Date|string|null;
219
+
220
+ /**
221
+ * The property indicates true only if the input has been entered by the user.
222
+ * In the case of programmatic changes, the property is reset to false.
223
+ * Read more about why this workaround is needed:
224
+ * https://github.com/vaadin/web-components/issues/5639
225
+ */
226
+ _hasInputValue: boolean|null|undefined;
197
227
  _overlayInitialized: boolean|null|undefined;
198
228
  ready(): void;
199
229
  disconnectedCallback(): void;
@@ -209,11 +239,19 @@ interface DatePickerMixin {
209
239
  close(): void;
210
240
  _onOverlayOpened(): void;
211
241
  _onOverlayClosed(): void;
242
+ _setInvalid(invalid: boolean): void;
243
+
244
+ /**
245
+ * Override this method to define whether the given `invalid` state should be set.
246
+ */
247
+ _shouldSetInvalid(_invalid: boolean): boolean;
212
248
 
213
249
  /**
214
- * Returns true if `value` is valid, and sets the `invalid` flag appropriately.
250
+ * Validates the field and sets the `invalid` property based on the result.
215
251
  *
216
- * @returns True if the value is valid and sets the `invalid` flag appropriately
252
+ * The method fires a `validated` event with the result of the validation.
253
+ *
254
+ * @returns True if the value is valid.
217
255
  */
218
256
  validate(): boolean;
219
257
 
@@ -226,6 +264,11 @@ interface DatePickerMixin {
226
264
  */
227
265
  checkValidity(): boolean;
228
266
  _focus(): void;
267
+
268
+ /**
269
+ * Sets the `_hasInputValue` property based on the `input` event.
270
+ */
271
+ _setHasInputValue(event: InputEvent|null): void;
229
272
  }
230
273
 
231
274
  import {DatePickerI18n} from '../@types/interfaces';
@@ -178,12 +178,22 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
178
178
  // Translation of the Cancel button text.
179
179
  cancel: 'Cancel',
180
180
 
181
+ // Used for adjusting the year value when parsing dates with short years.
182
+ // The year values between 0 and 99 are evaluated and adjusted.
183
+ // Example: for a referenceDate of 1970-10-30;
184
+ // dateToBeParsed: 40-10-30, result: 1940-10-30
185
+ // dateToBeParsed: 80-10-30, result: 1980-10-30
186
+ // dateToBeParsed: 10-10-30, result: 2010-10-30
187
+ // Supported date format: ISO 8601 `"YYYY-MM-DD"` (default)
188
+ // The default value is the current date.
189
+ referenceDate: '',
190
+
181
191
  // A function to format given `Object` as
182
192
  // date string. Object is in the format `{ day: ..., month: ..., year: ... }`
183
193
  // Note: The argument month is 0-based. This means that January = 0 and December = 11.
184
- formatDate: d => {
185
- // returns a string representation of the given
186
- // object in 'MM/DD/YYYY' -format
194
+ formatDate(d) {
195
+ const yearStr = String(d.year).replace(/\d+/, (y) => '0000'.substr(y.length) + y);
196
+ return [d.month + 1, d.day, yearStr].join('/');
187
197
  },
188
198
 
189
199
  // A function to parse the given text to an `Object` in the format `{ day: ..., month: ..., year: ... }`.
@@ -210,8 +220,18 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
210
220
  value: () => {
211
221
  return {
212
222
  monthNames: [
213
- 'January', 'February', 'March', 'April', 'May',
214
- 'June', 'July', 'August', 'September', 'October', 'November', 'December'
223
+ 'January',
224
+ 'February',
225
+ 'March',
226
+ 'April',
227
+ 'May',
228
+ 'June',
229
+ 'July',
230
+ 'August',
231
+ 'September',
232
+ 'October',
233
+ 'November',
234
+ 'December',
215
235
  ],
216
236
  weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
217
237
  weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
@@ -221,22 +241,24 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
221
241
  clear: 'Clear',
222
242
  today: 'Today',
223
243
  cancel: 'Cancel',
244
+ referenceDate: '',
224
245
  formatDate: d => {
225
246
  const yearStr = String(d.year).replace(/\d+/, y => '0000'.substr(y.length) + y);
226
247
  return [d.month + 1, d.day, yearStr].join('/');
227
248
  },
228
- parseDate: text => {
249
+ parseDate(text) {
229
250
  const parts = text.split('/');
230
251
  const today = new Date();
231
252
  let date, month = today.getMonth(), year = today.getFullYear();
232
253
 
233
254
  if (parts.length === 3) {
255
+ month = parseInt(parts[0]) - 1;
256
+ date = parseInt(parts[1]);
234
257
  year = parseInt(parts[2]);
235
258
  if (parts[2].length < 3 && year >= 0) {
236
- year += year < 50 ? 2000 : 1900;
259
+ const usedReferenceDate = this.referenceDate ? DatePickerHelper._parseDate(this.referenceDate) : new Date();
260
+ year = DatePickerHelper._getAdjustedYear(usedReferenceDate, year, month, date);
237
261
  }
238
- month = parseInt(parts[0]) - 1;
239
- date = parseInt(parts[1]);
240
262
  } else if (parts.length === 2) {
241
263
  month = parseInt(parts[0]) - 1;
242
264
  date = parseInt(parts[1]);
@@ -249,10 +271,10 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
249
271
  }
250
272
  },
251
273
  formatTitle: (monthName, fullYear) => {
252
- return monthName + ' ' + fullYear;
253
- }
274
+ return `${monthName} ${fullYear}`;
275
+ },
254
276
  };
255
- }
277
+ },
256
278
  },
257
279
 
258
280
  /**
@@ -310,6 +332,20 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
310
332
  computed: '_isNoInput(_fullscreen, _ios, i18n, i18n.*, opened, autoOpenDisabled)'
311
333
  },
312
334
 
335
+ /**
336
+ * The property indicates true only if the input has been entered by the user.
337
+ * In the case of programmatic changes, the property is reset to false.
338
+ * Read more about why this workaround is needed:
339
+ * https://github.com/vaadin/web-components/issues/5639
340
+ *
341
+ * @protected
342
+ */
343
+ _hasInputValue: {
344
+ type: Boolean,
345
+ value: false,
346
+ observer: '_hasInputValueChanged',
347
+ },
348
+
313
349
  /** @private */
314
350
  _ios: {
315
351
  type: Boolean,
@@ -375,7 +411,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
375
411
  }
376
412
  });
377
413
  this.addEventListener('keydown', this._onKeydown.bind(this));
378
- this.addEventListener('input', this._onUserInput.bind(this));
414
+ this.addEventListener('input', this.__onUserInput.bind(this));
379
415
  this.addEventListener('focus', e => this._noInput && e.target.blur());
380
416
  this.addEventListener('blur', e => {
381
417
  if (!this.opened) {
@@ -386,7 +422,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
386
422
  }
387
423
  }
388
424
 
389
- if (this._inputElement.value === '' && this.__dispatchChange) {
425
+ if (this._inputElementValue === '' && this.__dispatchChange) {
390
426
  this.validate();
391
427
  this.value = '';
392
428
  this.__dispatchChange = false;
@@ -752,7 +788,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
752
788
  // Select the parsed input or focused date
753
789
  this._ignoreFocusedDateChange = true;
754
790
  if (this.i18n.parseDate) {
755
- const inputValue = this._inputValue || '';
791
+ const inputValue = this._inputElementValue || '';
756
792
  const parsedDate = this._getParsedDate(inputValue);
757
793
 
758
794
  if (this._isValidDate(parsedDate)) {
@@ -796,16 +832,80 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
796
832
  }
797
833
 
798
834
  /**
799
- * Returns true if `value` is valid, and sets the `invalid` flag appropriately.
835
+ * A property for accessing the input element's value.
836
+ *
837
+ * Override this getter if the property is different from the default `value` one.
838
+ *
839
+ * @protected
840
+ * @return {string}
841
+ */
842
+ get _inputElementValueProperty() {
843
+ return 'value';
844
+ }
845
+
846
+ /**
847
+ * The input element's value.
848
+ *
849
+ * @protected
850
+ * @return {string}
851
+ */
852
+ get _inputElementValue() {
853
+ return this._inputElement ? this._inputElement[this._inputElementValueProperty] : undefined;
854
+ }
855
+
856
+ /**
857
+ * The setter resets the `_hasInputValue` property
858
+ * to false when the input element's value is updated programmatically.
859
+ * In date-picker, `_hasInputValue` is supposed to indicate true only
860
+ * if the input has been entered by the user.
861
+ * Read more about why this workaround is needed:
862
+ * https://github.com/vaadin/web-components/issues/5639
800
863
  *
801
- * @param {string=} value Value to validate. Optional, defaults to user's input value.
802
- * @return {boolean} True if the value is valid and sets the `invalid` flag appropriately
864
+ * @protected
865
+ */
866
+ set _inputElementValue(value) {
867
+ if (this._inputElement) {
868
+ this._inputElement[this._inputElementValueProperty] = value;
869
+ this._hasInputValue = false;
870
+ }
871
+ }
872
+
873
+ /**
874
+ * @param {boolean} invalid
875
+ * @protected
876
+ */
877
+ _setInvalid(invalid) {
878
+ if (this._shouldSetInvalid(invalid)) {
879
+ this.invalid = invalid;
880
+ }
881
+ }
882
+
883
+ /**
884
+ * Override this method to define whether the given `invalid` state should be set.
885
+ *
886
+ * @param {boolean} _invalid
887
+ * @return {boolean}
888
+ * @protected
889
+ */
890
+ _shouldSetInvalid(_invalid) {
891
+ return true;
892
+ }
893
+
894
+ /**
895
+ * Validates the field and sets the `invalid` property based on the result.
896
+ *
897
+ * The method fires a `validated` event with the result of the validation.
898
+ *
899
+ * @return {boolean} True if the value is valid.
803
900
  */
804
901
  validate() {
805
- // Note (Yuriy): Workaround `this._inputValue` is used in order
806
- // to avoid breaking change on custom `checkValidity`.
807
- // Can be removed with next major.
808
- return !(this.invalid = !this.checkValidity(this._inputValue));
902
+ // Note (Yuriy): this._inputElementValue is passed to checkValidity() as an argument to maintain
903
+ // backward compatibility in case it's being used in a custom implementation of checkValidity().
904
+ // The workaround can be removed with the next major.
905
+ const isValid = this.checkValidity(this._inputElementValue);
906
+ this._setInvalid(!isValid);
907
+ this.dispatchEvent(new CustomEvent('validated', {detail: {valid: isValid}}));
908
+ return isValid;
809
909
  }
810
910
 
811
911
  /**
@@ -817,8 +917,8 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
817
917
  * @return {boolean} True if the value is valid
818
918
  */
819
919
  checkValidity() {
820
- const inputValid = !this._inputValue ||
821
- (this._selectedDate && this._inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
920
+ const inputValid = !this._inputElementValue ||
921
+ (this._selectedDate && this._inputElementValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
822
922
  const minMaxValid = !this._selectedDate ||
823
923
  DatePickerHelper._dateAllowed(this._selectedDate, this._minDate, this._maxDate);
824
924
 
@@ -835,7 +935,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
835
935
  }
836
936
  }
837
937
 
838
- return inputValid && minMaxValid && inputValidity;
938
+ return !!(inputValid && minMaxValid && inputValidity);
839
939
  }
840
940
 
841
941
  /** @private */
@@ -857,12 +957,12 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
857
957
  /** @private */
858
958
  _focusAndSelect() {
859
959
  this._focus();
860
- this._setSelectionRange(0, this._inputValue.length);
960
+ this._setSelectionRange(0, this._inputElementValue.length);
861
961
  }
862
962
 
863
963
  /** @private */
864
964
  _applyInputValue(date) {
865
- this._inputValue = date ? this._getFormattedDate(this.i18n.formatDate, date) : '';
965
+ this._inputElementValue = date ? this._getFormattedDate(this.i18n.formatDate, date) : '';
866
966
  }
867
967
 
868
968
  /** @private */
@@ -935,7 +1035,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
935
1035
  }
936
1036
  this.close();
937
1037
  } else {
938
- if (!isValidDate && this._inputElement.value !== '') {
1038
+ if (!isValidDate && this._inputElementValue !== '') {
939
1039
  this.validate();
940
1040
  } else {
941
1041
  const oldValue = this.value;
@@ -953,7 +1053,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
953
1053
  this._close();
954
1054
  } else if (this.autoOpenDisabled) {
955
1055
  // Do not restore selected date if Esc was pressed after clearing input field
956
- if (this._inputElement.value === '') {
1056
+ if (this._inputElementValue === '') {
957
1057
  this._selectedDate = null;
958
1058
  }
959
1059
  this._applyInputValue(this._selectedDate);
@@ -980,16 +1080,50 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
980
1080
  }
981
1081
 
982
1082
  /** @private */
983
- _getParsedDate(inputValue = this._inputValue) {
1083
+ _getParsedDate(inputValue = this._inputElementValue) {
984
1084
  const dateObject = this.i18n.parseDate && this.i18n.parseDate(inputValue);
985
1085
  const parsedDate = dateObject &&
986
1086
  this._parseDate(dateObject.year + '-' + (dateObject.month + 1) + '-' + dateObject.day);
987
1087
  return parsedDate;
988
1088
  }
989
1089
 
1090
+ /**
1091
+ * Sets the `_hasInputValue` property based on the `input` event.
1092
+ *
1093
+ * @param {InputEvent} event
1094
+ * @protected
1095
+ */
1096
+ _setHasInputValue(event) {
1097
+ const target = event.composedPath()[0];
1098
+ this._hasInputValue = target.value.length > 0;
1099
+ }
1100
+
1101
+ /**
1102
+ * An input event listener used to update `_hasInputValue` property.
1103
+ * Do not override this method.
1104
+ *
1105
+ * @param {Event} event
1106
+ * @private
1107
+ */
1108
+ __onUserInput(event) {
1109
+ this._setHasInputValue(event);
1110
+ this._onUserInput(event);
1111
+ }
1112
+
1113
+ /**
1114
+ * Observer to notify about the change of private property.
1115
+ *
1116
+ * @private
1117
+ */
1118
+ _hasInputValueChanged(hasValue, oldHasValue) {
1119
+ if (hasValue || oldHasValue) {
1120
+ this.dispatchEvent(new CustomEvent('has-input-value-changed'));
1121
+ }
1122
+ }
1123
+
990
1124
  /** @private */
991
1125
  _onUserInput(e) {
992
- if (!this.opened && this._inputElement.value && !this.autoOpenDisabled) {
1126
+ if (!this.opened && this._inputElementValue && !this.autoOpenDisabled) {
993
1127
  this.open();
994
1128
  }
995
1129
  this._userInputValueChanged();
@@ -1004,7 +1138,7 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
1004
1138
 
1005
1139
  /** @private */
1006
1140
  _userInputValueChanged(value) {
1007
- if (this._inputValue) {
1141
+ if (this._inputElementValue) {
1008
1142
  const parsedDate = this._getParsedDate();
1009
1143
 
1010
1144
  if (this._isValidDate(parsedDate)) {
@@ -1028,10 +1162,17 @@ export const DatePickerMixin = subclass => class VaadinDatePickerMixin extends m
1028
1162
  get _overlayContent() {
1029
1163
  return this.$.overlay.content.querySelector('#overlay-content');
1030
1164
  }
1031
-
1032
1165
  /**
1033
1166
  * Fired when the user commits a value change.
1034
1167
  *
1035
1168
  * @event change
1036
1169
  */
1170
+
1171
+ /**
1172
+ * Fired whenever the field is validated.
1173
+ *
1174
+ * @event validated
1175
+ * @param {Object} detail
1176
+ * @param {boolean} detail.valid the result of the validation.
1177
+ */
1037
1178
  };
@@ -115,7 +115,6 @@ declare class DatePickerElement extends
115
115
  * Set to true to disable this element.
116
116
  */
117
117
  disabled: boolean;
118
- _inputValue: string;
119
118
 
120
119
  /**
121
120
  * Set to true to display the clear icon which clears the input.
@@ -147,7 +147,7 @@ class DatePickerElement extends
147
147
  }
148
148
 
149
149
  static get version() {
150
- return '4.4.5';
150
+ return '4.6.0';
151
151
  }
152
152
 
153
153
  static get properties() {
@@ -235,7 +235,7 @@ class DatePickerElement extends
235
235
  this._inputElement.addEventListener('change', (e) => {
236
236
  // For change event on text-field blur, after the field is cleared,
237
237
  // we schedule change event to be dispatched on date-picker blur.
238
- if (this._inputElement.value === '' && !e.__fromClearButton) {
238
+ if (this._inputElementValue === '' && !e.__fromClearButton) {
239
239
  this.__dispatchChange = true;
240
240
  }
241
241
  });
@@ -267,15 +267,6 @@ class DatePickerElement extends
267
267
  return this.$.input;
268
268
  }
269
269
 
270
- set _inputValue(value) {
271
- this._inputElement.value = value;
272
- }
273
-
274
- /** @return {string} */
275
- get _inputValue() {
276
- return this._inputElement.value;
277
- }
278
-
279
270
  /** @private */
280
271
  _getAriaExpanded(opened) {
281
272
  return Boolean(opened).toString();