Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat(date): Possibility to return invalid date #1384

Merged
merged 7 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions .changeset/metal-pants-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@baloise/ds-core': minor
---

**date**: the new property `allow-invalid-value` includes a functionality where it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
1 change: 0 additions & 1 deletion docs/public/assets/css/baloise-design-system.min.css

This file was deleted.

21 changes: 21 additions & 0 deletions e2e/cypress/component/bal-date.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,25 @@ describe('bal-date', () => {
cy.get('@balChange').should('have.been.calledOnce')
cy.get('@balChange').shouldHaveEventDetail('2022-12-11')
})

it('check if invalid date is returned', () => {
onBalChangeSpy = cy.spy().as('balChange')
cy.mount<Components.BalDate, HTMLBalDateElementEventMap>(`<bal-date allow-invalid-value></bal-date>`, {
props: {
defaultDate: '2023-01-01',
placeholder: 'Enter date',
},
events: {
balChange: onBalChangeSpy,
},
}).as('calendar')

cy.getByPlaceholder('Enter date')
.click()
.type('2.42.2023', { delay: 20 })
.blur({ force: true })
.should('have.value', '02.42.2023')
cy.get('@balChange').should('have.been.calledOnce')
cy.get('@balChange').shouldHaveEventDetail('INVALID_VALUE')
})
})
16 changes: 16 additions & 0 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,10 @@ export namespace Components {
"multiline": boolean;
}
interface BalDate {
/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
"allowInvalidValue": boolean;
/**
* Callback to determine which date in the datepicker should be selectable.
*/
Expand Down Expand Up @@ -1535,6 +1539,10 @@ export namespace Components {
"value"?: string;
}
interface BalInputDate {
/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
"allowInvalidValue": boolean;
/**
* If `true`, in Angular reactive forms the control will not be set invalid
*/
Expand Down Expand Up @@ -5736,6 +5744,10 @@ declare namespace LocalJSX {
"onBalFocus"?: (event: BalDataValueCustomEvent<BalEvents.BalDataValueFocusDetail>) => void;
}
interface BalDate {
/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
"allowInvalidValue"?: boolean;
/**
* Callback to determine which date in the datepicker should be selectable.
*/
Expand Down Expand Up @@ -6575,6 +6587,10 @@ declare namespace LocalJSX {
"value"?: string;
}
interface BalInputDate {
/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
"allowInvalidValue"?: boolean;
/**
* If `true`, in Angular reactive forms the control will not be set invalid
*/
Expand Down
8 changes: 7 additions & 1 deletion packages/core/src/components/bal-date/bal-date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ export class Date implements ComponentInterface, Loggable, BalAriaFormLinking {
/**
* Callback to determine which date in the datepicker should be selectable.
*/
@Prop({ attribute: 'allowed-dates' }) allowedDates: BalProps.BalDateCallback | undefined = undefined
@Prop() allowedDates: BalProps.BalDateCallback | undefined = undefined

/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
@Prop() allowInvalidValue = false
yannickholzenkamp marked this conversation as resolved.
Show resolved Hide resolved

/**
* Set the amount of time, in milliseconds, to wait to trigger the `ionChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`.
Expand Down Expand Up @@ -492,6 +497,7 @@ export class Date implements ComponentInterface, Loggable, BalAriaFormLinking {
invalid={this.invalid}
readonly={this.readonly}
disabled={this.disabled}
allowInvalidValue={this.allowInvalidValue}
onClick={this.onInputClick}
onBalInput={this.onInputInput}
onBalChange={this.onInputChange}
Expand Down
37 changes: 21 additions & 16 deletions packages/core/src/components/bal-date/test/bal-date.cy.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,28 @@
</head>

<body>
<bal-doc-app>
<bal-doc-app log-components="bal-date">
<main class="container">
<form action="https://www.w3schools.com/action_page.php" target="_blank">
<bal-form-grid>
<bal-form-col>
<bal-field required>
<bal-field-control>
<bal-date data-testid="reset" value="2022-09-16"></bal-date>
</bal-field-control>
</bal-field>
</bal-form-col>
</bal-form-grid>
<bal-button-group>
<bal-button element-type="submit" color="primary">Submit</bal-button>
<bal-button data-testid="button-reset" element-type="reset" color="link">Reset</bal-button>
</bal-button-group>
</form>
<section>
<form action="https://www.w3schools.com/action_page.php" target="_blank">
<bal-form-grid>
<bal-form-col>
<bal-field required>
<bal-field-control>
<bal-date data-testid="reset" value="2022-09-16"></bal-date>
</bal-field-control>
</bal-field>
</bal-form-col>
</bal-form-grid>
<bal-button-group>
<bal-button element-type="submit" color="primary">Submit</bal-button>
<bal-button data-testid="button-reset" element-type="reset" color="link">Reset</bal-button>
</bal-button-group>
</form>
</section>
<section class="mt-large">
<bal-date data-testid="allow-invalid-value" value="2022-12-16" allow-invalid-value></bal-date>
</section>
</main>
</bal-doc-app>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ export class InputDate implements ComponentInterface, Loggable, BalConfigObserve
*/
@Prop({ reflect: true }) autoInvalidOff = false

/**
* If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
*/
@Prop() allowInvalidValue = false

/**
* Emitted when a keyboard key has pressed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { MaskComponent } from '../component'

export class MaskComponentMock implements MaskComponent {
value: string | undefined = undefined
allowInvalidValue = false
inputValue: string | undefined = undefined
initialValue = ''
focused = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface MaskComponentAdapterType {

export interface MaskComponent {
value: string | undefined
allowInvalidValue: boolean
inputValue: string | undefined
initialValue: string
focused: boolean
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/utils/mask/context/mask-context.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { MaskComponent } from '../component'
import { MaskContextEvent, MaskContextOptions } from './mask-context-interfaces'
import { MaskPosition } from './mask-position'

export abstract class MaskContext<T = MaskContextEvent> {
private _value = ''
public position!: MaskPosition
public component!: MaskComponent

constructor(protected _options: MaskContextOptions<T>) {
if (this._options.component && this._options.component.nativeInput) {
this._value = this._options.component.nativeInput.value
}
this.position = new MaskPosition(this._options)
this.component = this._options.component
}

get target(): HTMLInputElement | undefined {
Expand Down
9 changes: 7 additions & 2 deletions packages/core/src/utils/mask/mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
import { Mask } from './mask-interfaces'

export abstract class AbstractMask implements Mask {
public static INVALID_VALUE = 'INVALID_VALUE'

public abstract maxLength: number
public abstract minLength: number
public inputMode: BalProps.BalInputInputMode = 'text'
Expand Down Expand Up @@ -114,7 +116,7 @@ export abstract class AbstractMask implements Mask {
context.position.toEnd()
}

public onParseValue(inputValue?: string) {
public onParseValue(inputValue?: string, options: { allowInvalidValue: boolean } = { allowInvalidValue: false }) {
if (inputValue) {
return inputValue.trim()
}
Expand Down Expand Up @@ -189,7 +191,10 @@ export abstract class AbstractMask implements Mask {
this.emptyInputValue(context)
} else {
this.onBlur(context)
context.submit('blur', this.onParseValue(context.value))
context.submit(
'blur',
this.onParseValue(context.value, { allowInvalidValue: context.component.allowInvalidValue }),
)
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/utils/mask/types/mask-date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,13 @@ export class DateMask extends AbstractMask {
])
}

override onParseValue(inputValue?: string): string {
override onParseValue(inputValue?: string, options: { allowInvalidValue: boolean } = { allowInvalidValue: false }): string {
if (inputValue) {
const date = BalDate.fromAnyFormat(this.blocks.getRawValueWithoutMask(inputValue))
if (date.isValid) {
return date.toISODate()
} else if (options && options.allowInvalidValue) {
return AbstractMask.INVALID_VALUE
}
}
return ''
Expand Down Expand Up @@ -122,11 +124,16 @@ export class DateMask extends AbstractMask {
override onBlur(context: MaskFocusContext) {
const rawValue = this.blocks.getRawValueWithoutMaskByContext(context)
const date = BalDate.fromAnyFormat(rawValue)

if (date.isValid) {
const formattedDate = date.toFormat()
if (formattedDate !== context.value) {
context.value = formattedDate
}
} else if (context.component.allowInvalidValue) {
if (rawValue !== context.value) {
context.value = rawValue
}
}
}
}
Loading