fix(LionInputDatePicker): remove endless loop on InvalidDate modelValue (#1984)

* refactor: used IsDate validator instead of custom isValidDate function

* fix: used IsDate validator to validate modelValue before it's passed to lion-calendar's selctedDate

* test: Updated lion-input-datepicker tests to include example of handling invalid modelValue

* docs: Updated docs to include example with invalid modelValue

* refactor: updated returned type of __getSyncDownValue method

* changset: updated changeset for @lion/ui

* refactor: linting fix

* refactor:  import path updated

Co-authored-by: gerjanvangeest <gerjanvangeest@users.noreply.github.com>

* refactor: label added to Faulty prefilled datepicker input

Co-authored-by: gerjanvangeest <gerjanvangeest@users.noreply.github.com>

* test: updated test to include more obvious invalid date value

---------

Co-authored-by: gerjanvangeest <gerjanvangeest@users.noreply.github.com>
This commit is contained in:
Monika Nawój 2023-05-24 11:51:26 +02:00 committed by GitHub
parent d4085cc8c0
commit e310c08af1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 13 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': minor
---
fix: LionInputDatePicker enters an endless loop on InvalidDate modelValue

View file

@ -76,3 +76,14 @@ export const readOnly = () => html`
</lion-input-datepicker>
`;
```
## Faulty prefilled
Faulty prefilled input will be cleared
```js preview-story
export const faultyPrefilled = () => html`
<lion-input-datepicker label="Faulty prefiiled" .modelValue="${new Date('30/01/2022')}">
</lion-input-datepicker>
`;
```

View file

@ -2,16 +2,6 @@ import { IsDate } from '@lion/ui/form-core.js';
import { LionInput } from '@lion/ui/input.js';
import { formatDate, LocalizeMixin, parseDate } from '@lion/ui/localize-no-side-effects.js';
/**
* @param {Date|number} date
*/
function isValidDate(date) {
// to make sure it is a valid date we use isNaN and not Number.isNaN
// @ts-ignore [allow]: dirty hack, you're not supposed to pass Date instances to isNaN
// eslint-disable-next-line no-restricted-globals
return date instanceof Date && !isNaN(date);
}
/**
* `LionInputDate` has a .modelValue of type Date. It parses, formats and validates based
* on locale.
@ -51,7 +41,8 @@ export class LionInputDate extends LocalizeMixin(LionInput) {
*/
// eslint-disable-next-line class-methods-use-this
serializer(modelValue) {
if (!isValidDate(modelValue)) {
const isDate = new IsDate();
if (isDate.execute(modelValue)) {
return '';
}
// modelValue is localized, so we take the timezone offset in milliseconds and subtract it

View file

@ -4,6 +4,7 @@ import { ScopedElementsMixin } from '@open-wc/scoped-elements';
import { html, css } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js';
import { LionInputDate } from '@lion/ui/input-date.js';
import { IsDate } from '@lion/ui/form-core.js';
import {
OverlayMixin,
withBottomSheetConfig,
@ -376,7 +377,9 @@ export class LionInputDatepicker extends ScopedElementsMixin(
* @returns {Date | undefined} a 'guarded' modelValue
*/
static __getSyncDownValue(modelValue) {
return modelValue instanceof Date ? modelValue : undefined;
const isDate = new IsDate();
const hasError = isDate.execute(modelValue);
return hasError ? undefined : modelValue;
}
/**

View file

@ -360,6 +360,26 @@ describe('<lion-input-datepicker>', () => {
expect(el.__calendarMaxDate.toString()).to.equal(new Date('2019/07/15').toString());
});
it('should show error on invalid date passed to modelValue', async () => {
const myDate = new Date('foo');
const el = await fixture(html`
<lion-input-datepicker .modelValue="${myDate}"></lion-input-datepicker>
`);
expect(el.hasFeedbackFor).to.include('error');
expect(el.validationStates).to.have.property('error');
expect(el.validationStates.error).to.have.property('IsDate');
});
it('should show error on date with invalid format passed to modelValue', async () => {
const myDate = new Date('30/01/2022');
const el = await fixture(html`
<lion-input-datepicker .modelValue="${myDate}"></lion-input-datepicker>
`);
expect(el.hasFeedbackFor).to.include('error');
expect(el.validationStates).to.have.property('error');
expect(el.validationStates.error).to.have.property('IsDate');
});
/**
* Not in scope:
* - min/max attr (like platform has): could be added in future if observers needed