Skip to content

Commit 228c3b5

Browse files
DataForm select control: support validation (WordPress#71665)
Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
1 parent 9f492ef commit 228c3b5

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-5
lines changed

packages/components/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- `ValidatedCheckboxControl`: Expose the component under private API's ([#71505](https://github.com/WordPress/gutenberg/pull/71505/)).
1212
- Expose `ValidatedTextareaControl` via Private APIs ([#71495](https://github.com/WordPress/gutenberg/pull/71495))
1313
- Add support for ValidatedFormTokenField [#71350](https://github.com/WordPress/gutenberg/pull/71350).
14+
- Expose `ValidatedSelectControl` via Private APIs ([#71665](https://github.com/WordPress/gutenberg/pull/71665))
1415

1516
## 30.3.0 (2025-09-03)
1617

packages/components/src/private-apis.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
ValidatedCheckboxControl,
1717
ValidatedInputControl,
1818
ValidatedNumberControl,
19+
ValidatedSelectControl,
1920
ValidatedTextControl,
2021
ValidatedTextareaControl,
2122
ValidatedToggleControl,
@@ -40,6 +41,7 @@ lock( privateApis, {
4041
ValidatedInputControl,
4142
ValidatedCheckboxControl,
4243
ValidatedNumberControl,
44+
ValidatedSelectControl,
4345
ValidatedTextControl,
4446
ValidatedTextareaControl,
4547
ValidatedToggleControl,

packages/dataviews/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- Dataform: Add new `password` field type and field control. [#71545](https://github.com/WordPress/gutenberg/pull/71545)
1717
- DataForm: Add a textarea control for use with the `text` field type ([#71495](https://github.com/WordPress/gutenberg/pull/71495))
1818
- DataViews: support groupBy in the list layout. [#71548](https://github.com/WordPress/gutenberg/pull/71548)
19+
- DataForm: support validation in select control [#71665](https://github.com/WordPress/gutenberg/pull/71665)
1920

2021
### Bug Fixes
2122

packages/dataviews/src/components/dataform/stories/index.story.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ const ValidationComponent = ( {
396396
} ) => {
397397
type ValidatedItem = {
398398
text: string;
399+
select?: string;
399400
textarea: string;
400401
email: string;
401402
telephone: string;
@@ -409,6 +410,7 @@ const ValidationComponent = ( {
409410

410411
const [ post, setPost ] = useState< ValidatedItem >( {
411412
text: 'Can have letters and spaces',
413+
select: undefined,
412414
textarea: 'Can have letters and spaces',
413415
email: 'hi@example.com',
414416
telephone: '+306978241796',
@@ -427,6 +429,13 @@ const ValidationComponent = ( {
427429

428430
return null;
429431
};
432+
const customSelectRule = ( value: ValidatedItem ) => {
433+
if ( value.select !== 'option1' ) {
434+
return 'Value must be Option 1.';
435+
}
436+
437+
return null;
438+
};
430439
const customTextareaRule = ( value: ValidatedItem ) => {
431440
if ( ! /^[a-zA-Z ]+$/.test( value.textarea ) ) {
432441
return 'Value must only contain letters and spaces.';
@@ -500,6 +509,19 @@ const ValidationComponent = ( {
500509
custom: maybeCustomRule( customTextRule ),
501510
},
502511
},
512+
{
513+
id: 'select',
514+
type: 'text',
515+
label: 'Select',
516+
elements: [
517+
{ value: 'option1', label: 'Option 1' },
518+
{ value: 'option2', label: 'Option 2' },
519+
],
520+
isValid: {
521+
required,
522+
custom: maybeCustomRule( customSelectRule ),
523+
},
524+
},
503525
{
504526
id: 'textarea',
505527
type: 'text',
@@ -586,6 +608,7 @@ const ValidationComponent = ( {
586608
layout: { type },
587609
fields: [
588610
'text',
611+
'select',
589612
'textarea',
590613
'email',
591614
'telephone',

packages/dataviews/src/dataform-controls/select.tsx

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
/**
22
* WordPress dependencies
33
*/
4-
import { SelectControl } from '@wordpress/components';
5-
import { useCallback } from '@wordpress/element';
4+
import { privateApis } from '@wordpress/components';
5+
import { useCallback, useState } from '@wordpress/element';
66
import { __ } from '@wordpress/i18n';
77

88
/**
99
* Internal dependencies
1010
*/
1111
import type { DataFormControlProps } from '../types';
12+
import { unlock } from '../lock-unlock';
13+
14+
const { ValidatedSelectControl } = unlock( privateApis );
1215

1316
export default function Select< Item >( {
1417
data,
1518
field,
1619
onChange,
1720
hideLabelFromVision,
1821
}: DataFormControlProps< Item > ) {
19-
const { id, label, type } = field;
22+
const { id, type, label, description } = field;
23+
const [ customValidity, setCustomValidity ] =
24+
useState<
25+
React.ComponentProps<
26+
typeof ValidatedSelectControl
27+
>[ 'customValidity' ]
28+
>( undefined );
29+
2030
const isMultiple = type === 'array';
2131
const value = field.getValue( { item: data } ) ?? ( isMultiple ? [] : '' );
2232
const onChangeControl = useCallback(
@@ -48,10 +58,31 @@ export default function Select< Item >( {
4858
];
4959

5060
return (
51-
<SelectControl
61+
<ValidatedSelectControl
62+
required={ !! field.isValid?.required }
63+
onValidate={ ( newValue: any ) => {
64+
const message = field.isValid?.custom?.(
65+
{
66+
...data,
67+
[ id ]: newValue,
68+
},
69+
field
70+
);
71+
72+
if ( message ) {
73+
setCustomValidity( {
74+
type: 'invalid',
75+
message,
76+
} );
77+
return;
78+
}
79+
80+
setCustomValidity( undefined );
81+
} }
82+
customValidity={ customValidity }
5283
label={ label }
5384
value={ value }
54-
help={ field.description }
85+
help={ description }
5586
options={ elements }
5687
onChange={ onChangeControl }
5788
__next40pxDefaultSize

0 commit comments

Comments
 (0)