Skip to content

Commit

Permalink
fix validations for controlled datefield components (#5991)
Browse files Browse the repository at this point in the history
* fix validations for controlled components
  • Loading branch information
tomekancu committed Apr 22, 2024
1 parent 1d70153 commit 72775d2
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 8 deletions.
6 changes: 3 additions & 3 deletions packages/@react-stately/form/src/useFormValidationState.ts
Expand Up @@ -81,9 +81,9 @@ function useFormValidationStateImpl<T>(props: FormValidationProps<T>): FormValid
isInvalid ||= validationState === 'invalid';
}

// If the isInvalid prop is true, update validation result in realtime (controlled).
let controlledError: ValidationResult | null = isInvalid ? {
isInvalid: true,
// If the isInvalid prop is controlled, update validation result in realtime.
let controlledError: ValidationResult | null = isInvalid !== undefined ? {
isInvalid,
validationErrors: [],
validationDetails: CUSTOM_VALIDITY_STATE
} : null;
Expand Down
47 changes: 42 additions & 5 deletions packages/react-aria-components/stories/DateField.stories.tsx
Expand Up @@ -10,21 +10,58 @@
* governing permissions and limitations under the License.
*/

import {action} from '@storybook/addon-actions';
import clsx from 'clsx';
import {DateField, DateInput, DateSegment, Label} from 'react-aria-components';
import {parseAbsoluteToLocal} from '@internationalized/date';
import {DateField, DateInput, DateSegment, FieldError, Label} from 'react-aria-components';
import {fromAbsolute, getLocalTimeZone, parseAbsoluteToLocal} from '@internationalized/date';
import React from 'react';
import styles from '../example/index.css';

export default {
title: 'React Aria Components'
title: 'React Aria Components',
argTypes: {
onChange: {
table: {
disable: true
}
},
granularity: {
control: 'select',
options: ['day', 'hour', 'minute', 'second']
},
minValue: {
control: 'date'
},
maxValue: {
control: 'date'
},
isRequired: {
control: 'boolean'
},
isInvalid: {
control: 'boolean'
},
validationBehavior: {
control: 'select',
options: ['native', 'aria']
}
},
args: {
onChange: action('OnChange')
}
};

export const DateFieldExample = () => (
<DateField data-testid="date-field-example" defaultValue={parseAbsoluteToLocal('2024-01-01T01:01:00Z')}>
export const DateFieldExample = (props) => (
<DateField
{...props}
minValue={props.minValue ? fromAbsolute(props.minValue, getLocalTimeZone()) : undefined}
maxValue={props.maxValue ? fromAbsolute(props.maxValue, getLocalTimeZone()) : undefined}
data-testid="date-field-example"
defaultValue={parseAbsoluteToLocal('2024-01-01T01:01:00Z')}>
<Label style={{display: 'block'}}>Date</Label>
<DateInput className={styles.field} data-testid2="date-input">
{segment => <DateSegment segment={segment} className={clsx(styles.segment, {[styles.placeholder]: segment.isPlaceholder})} />}
</DateInput>
<FieldError style={{display: 'block'}} />
</DateField>
);
27 changes: 27 additions & 0 deletions packages/react-aria-components/test/DateField.test.js
Expand Up @@ -259,6 +259,33 @@ describe('DateField', () => {
expect(group).not.toHaveAttribute('data-invalid');
});

it('should use controlled validation first', async () => {
let {getByRole, getByTestId} = render(
<form data-testid="form">
<DateField name="date" isRequired isInvalid={false}>
<Label>Birth Date</Label>
<DateInput>
{segment => <DateSegment segment={segment} />}
</DateInput>
<FieldError />
</DateField>
</form>
);

let group = getByRole('group');
let input = document.querySelector('input[name=date]');
expect(input).toHaveAttribute('required');
expect(input.validity.valid).toBe(false);
expect(group).not.toHaveAttribute('aria-describedby');
expect(group).not.toHaveAttribute('data-invalid');

act(() => {getByTestId('form').checkValidity();});

expect(input.validity.valid).toBe(false);
expect(group).not.toHaveAttribute('aria-describedby');
expect(group).not.toHaveAttribute('data-invalid');
});

it('should focus previous segment when backspacing on an empty date segment', async () => {
let {getAllByRole} = render(
<DateField defaultValue={new CalendarDate(2024, 12, 31)}>
Expand Down

1 comment on commit 72775d2

@rspbot
Copy link

@rspbot rspbot commented on 72775d2 Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.