diff --git a/packages/dataviews/src/components/dataform/index.tsx b/packages/dataviews/src/components/dataform/index.tsx index 42a6766813975..bd38dca472af0 100644 --- a/packages/dataviews/src/components/dataform/index.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -9,7 +9,9 @@ import type { Dispatch, SetStateAction } from 'react'; import { TextControl, __experimentalNumberControl as NumberControl, + SelectControl, } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; import { useCallback, useMemo } from '@wordpress/element'; /** @@ -65,8 +67,7 @@ function DataFormNumberControl< Item >( { onChange, }: DataFormControlProps< Item > ) { const { id, label, description } = field; - const value = field.getValue( { item: data } ); - + const value = field.getValue( { item: data } ) ?? ''; const onChangeControl = useCallback( ( newValue: string | undefined ) => onChange( ( prevItem: Item ) => ( { @@ -76,6 +77,29 @@ function DataFormNumberControl< Item >( { [ id, onChange ] ); + if ( field.elements ) { + const elements = [ + /* + * Value can be undefined when: + * + * - the field is not required + * - in bulk editing + * + */ + { label: __( 'Select item' ), value: '' }, + ...field.elements, + ]; + + return ( + + ); + } + return ( { const [ post, setPost ] = useState( { title: 'Hello, World!', order: 2, + author: 1, } ); const form = { - visibleFields: [ 'title', 'order' ], + visibleFields: [ 'title', 'order', 'author' ], }; return ( diff --git a/packages/dataviews/src/test/validation.ts b/packages/dataviews/src/test/validation.ts index d90d4744ac327..ded002e5bc042 100644 --- a/packages/dataviews/src/test/validation.ts +++ b/packages/dataviews/src/test/validation.ts @@ -60,4 +60,21 @@ describe( 'validation', () => { const result = isItemValid( item, fields, form ); expect( result ).toBe( false ); } ); + + it( 'field is invalid if value is not one of the elements', () => { + const item = { id: 1, author: 3 }; + const fields: Field< {} >[] = [ + { + id: 'author', + type: 'integer', + elements: [ + { value: 1, label: 'Jane' }, + { value: 2, label: 'John' }, + ], + }, + ]; + const form = { visibleFields: [ 'author' ] }; + const result = isItemValid( item, fields, form ); + expect( result ).toBe( false ); + } ); } ); diff --git a/packages/dataviews/src/validation.ts b/packages/dataviews/src/validation.ts index 5b20d094a4186..a6d3515fe6e57 100644 --- a/packages/dataviews/src/validation.ts +++ b/packages/dataviews/src/validation.ts @@ -27,6 +27,13 @@ export function isItemValid< Item >( return false; } + if ( field.elements ) { + const validValues = field.elements.map( ( f ) => f.value ); + if ( ! validValues.includes( Number( value ) ) ) { + return false; + } + } + // Nothing to validate. return true; } ); diff --git a/packages/edit-site/src/components/post-edit/index.js b/packages/edit-site/src/components/post-edit/index.js index 21dbb10e51466..f8519470749a9 100644 --- a/packages/edit-site/src/components/post-edit/index.js +++ b/packages/edit-site/src/components/post-edit/index.js @@ -7,7 +7,7 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { DataForm } from '@wordpress/dataviews'; +import { DataForm, isItemValid } from '@wordpress/dataviews'; import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { store as coreDataStore } from '@wordpress/core-data'; import { Button } from '@wordpress/components'; @@ -42,7 +42,7 @@ function PostEditForm( { postType, postId } ) { const { saveEntityRecord } = useDispatch( coreDataStore ); const { fields } = usePostFields(); const form = { - visibleFields: [ 'title' ], + visibleFields: [ 'title', 'author' ], }; const [ edits, setEdits ] = useState( {} ); const itemWithEdits = useMemo( () => { @@ -53,6 +53,11 @@ function PostEditForm( { postType, postId } ) { }, [ initialEdits, edits ] ); const onSubmit = async ( event ) => { event.preventDefault(); + + if ( ! isItemValid( itemWithEdits, fields, form ) ) { + return; + } + const { getEntityRecord } = registry.resolveSelect( coreDataStore ); for ( const id of ids ) { const item = await getEntityRecord( 'postType', postType, id ); @@ -64,6 +69,7 @@ function PostEditForm( { postType, postId } ) { setEdits( {} ); }; + const isUpdateDisabled = ! isItemValid( itemWithEdits, fields, form ); return (
- diff --git a/packages/edit-site/src/components/post-fields/index.js b/packages/edit-site/src/components/post-fields/index.js index f4e8e553c8fa4..52030fc70f54b 100644 --- a/packages/edit-site/src/components/post-fields/index.js +++ b/packages/edit-site/src/components/post-fields/index.js @@ -235,7 +235,7 @@ function usePostFields( viewType ) { { label: __( 'Author' ), id: 'author', - getValue: ( { item } ) => item._embedded?.author[ 0 ]?.name, + type: 'integer', elements: authors?.map( ( { id, name } ) => ( { value: id,