Skip to content

Commit

Permalink
va-date: add prop to make month optional (#1377)
Browse files Browse the repository at this point in the history
  • Loading branch information
it-harrison authored Oct 25, 2024
1 parent ed309fc commit 32ae6e9
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 9 deletions.
6 changes: 6 additions & 0 deletions packages/storybook/stories/va-date.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultArgs = {
'error': undefined,
'value': undefined,
'month-year-only': undefined,
'month-optional': false,
'enable-analytics': false,
};

Expand All @@ -36,6 +37,7 @@ const Template = ({
'month-year-only': monthYearOnly,
value,
'enable-analytics': enableAnalytics,
'month-optional': monthOptional
}) => {
return (
<VaDate
Expand All @@ -45,6 +47,7 @@ const Template = ({
error={error}
value={value}
monthYearOnly={monthYearOnly}
monthOptional={monthOptional}
onDateBlur={e => {
console.log(e, 'DATE BLUR FIRED');
console.log(e.target.value);
Expand Down Expand Up @@ -181,6 +184,9 @@ WithHintTextError.args = {
export const MonthYear = Template.bind({});
MonthYear.args = { ...defaultArgs, 'month-year-only': true };

export const MonthOptional = Template.bind({});
MonthOptional.args = {...defaultArgs, 'month-year-only': true, 'month-optional': true}

export const CustomValidation = CustomValidationTemplate.bind(null);
CustomValidation.args = {
...defaultArgs,
Expand Down
8 changes: 8 additions & 0 deletions packages/web-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,10 @@ export namespace Components {
* Label for the field.
*/
"label": string;
/**
* Whether month should be optional; has no effect unless monthYearOnly is true
*/
"monthOptional"?: boolean;
/**
* Whether or not only the Month and Year inputs should be displayed.
*/
Expand Down Expand Up @@ -3534,6 +3538,10 @@ declare namespace LocalJSX {
* Label for the field.
*/
"label": string;
/**
* Whether month should be optional; has no effect unless monthYearOnly is true
*/
"monthOptional"?: boolean;
/**
* Whether or not only the Month and Year inputs should be displayed.
*/
Expand Down
17 changes: 17 additions & 0 deletions packages/web-components/src/components/va-date/test/va-date.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,21 @@ describe('va-date', () => {
});
});

it('month is not required if month-year-only and month-optional props set', async () => {
const page = await newE2EPage();
await page.setContent('<va-date name="test" month-year-only month-optional/>');

const handleYear = await page.$('pierce/[name="testYear"]');
const handleMonth = await page.$('pierce/[name="testMonth"]');

await handleMonth.press('Tab');
await handleYear.press('Tab');
await page.waitForChanges();

const getAriaInvalid =
(element: HTMLElement) => element.getAttribute('aria-invalid');

let month = await handleMonth.evaluate(getAriaInvalid);
expect(month).toEqual('false');
})
});
9 changes: 8 additions & 1 deletion packages/web-components/src/components/va-date/va-date.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export class VaDate {
*/
@Prop() monthYearOnly?: boolean = false;

/**
* Whether month should be optional; has no effect unless monthYearOnly is true
*/
@Prop() monthOptional?: boolean = false;

/**
* Set the default date value must be in YYYY-MM-DD format.
*/
Expand Down Expand Up @@ -152,7 +157,9 @@ export class VaDate {
yearTouched: this.yearTouched,
monthTouched: this.monthTouched,
dayTouched: this.dayTouched,
monthSelect: true
monthSelect: true,
monthYearOnly: this.monthYearOnly,
monthOptional: this.monthOptional
});

if (this.error) {
Expand Down
19 changes: 11 additions & 8 deletions packages/web-components/src/utils/date-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ interface ValidateConfig {
yearTouched?: boolean,
monthTouched?: boolean,
dayTouched?: boolean,
monthSelect?: boolean
monthSelect?: boolean,
monthOptional?: boolean
}

export function validate({
Expand All @@ -191,18 +192,20 @@ export function validate({
yearTouched,
monthTouched,
dayTouched,
monthSelect
monthSelect,
monthOptional
}: ValidateConfig): void {

const maxDays = daysForSelectedMonth(year, month);

// Reset previous invalid states
component.invalidYear = false;
component.invalidMonth = false;
component.invalidDay = false;

const monthRequired = !(monthYearOnly && monthOptional);

// Check NaN and set errors based on NaN values
if (isNaN(month) && monthTouched) {
if (monthRequired && isNaN(month) && monthTouched) {
component.invalidMonth = true;
component.error = getMonthErrorKey(monthSelect);
return;
Expand All @@ -219,8 +222,8 @@ export function validate({
}

// Validate required fields
if (component.required && (!year || !month || (!monthYearOnly && !day))) {
if (monthTouched && !month) {
if (component.required && (!year || (monthRequired && !month) || (!monthYearOnly && !day))) {
if (monthRequired && monthTouched && !month) {
component.invalidMonth = true;
component.error = 'date-error';
return;
Expand All @@ -238,7 +241,7 @@ export function validate({
}

// Check for empty values after the fields are touched
if (!month && monthTouched) {
if (monthRequired && !month && monthTouched) {
component.invalidMonth = true;
component.error = getMonthErrorKey(monthSelect);
return;
Expand All @@ -255,7 +258,7 @@ export function validate({
}

// Validate year, month, and day ranges if they have a value regardless of whether they are required
if (month && (month < minMonths || month > maxMonths) && monthTouched) {
if (monthRequired && month && (month < minMonths || month > maxMonths) && monthTouched) {
component.invalidMonth = true;
component.error = getMonthErrorKey(monthSelect);
return;
Expand Down

0 comments on commit 32ae6e9

Please sign in to comment.