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,