woocommerce/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/data-store/validation.md

11 KiB

Validation Store (wc/store/validation)

Table of Contents

Overview

The validation data store provides a way to show errors for fields in the Cart or Checkout blocks.

The data in the store should be a single object, the keys of which are the error IDs and values are the data associated with that error message. The values in the object should contain message and hidden. The message is the error message to display and hidden is a boolean indicating whether the error should be shown or not.

An example of how the data should be structured:

{
    "error-id-1": {
        message: "This is an error message",
        hidden: false,
    },
    "error-id-2": {
        message: "This is another error message",
        hidden: true,
    },
}

When the checkout process begins, it will check if this data store has any entries, and if so, it will stop the checkout process from proceeding. It will also show any errors that are hidden. Setting an error to hidden will not clear it from the data store!

Usage

To utilize this store you will import the CART_STORE_KEY in any module referencing it. Assuming @woocommerce/block-data is registered as an external pointing to wc.wcBlocksData you can import the key via:

const { VALIDATION_STORE_KEY } = window.wc.wcBlocksData;

Example

To better understand the Validation Store, let's use the required checkbox of the Terms and Conditions as an example. In the page editor, a merchant can define that a buyer must agree to the Terms and Conditions by making the checkbox required.

image

In WooCommerce Blocks, we're using a useEffect hook to check if the checkbox is required and if it is checked. If the checkbox is required and not checked, we're adding a validation error to the store. If the checkbox is required and checked, we're clearing the validation error from the store.

useEffect( () => {
	if ( ! checkbox ) {
		return;
	}
	if ( checked ) {
		clearValidationError( validationErrorId );
	} else {
		setValidationErrors( {
			[ validationErrorId ]: {
				message: __(
					'Please read and accept the terms and conditions.',
					'woo-gutenberg-products-block'
				),
				hidden: true,
			},
		} );
	}
	return () => {
		clearValidationError( validationErrorId );
	};
}, [
	checkbox,
	checked,
	validationErrorId,
	clearValidationError,
	setValidationErrors,
] );

By default, the validation error is hidden. This is because we don't want to show the error message until the buyer has tried to submit the form. Before submitting the checkout form, the validation message can already be seen in the Validation Store.

image

When a buyer submits the checkout form without checking the Terms and Conditions checkbox, the entry hidden: true will be changed to hidden: false and the validation message is shown.

image

In WooCommerce Blocks, we're checking if text input fields have a validation error using the following code:

const hasError = validationError?.message && ! validationError?.hidden;

💡 The main point to remember from this example is:

  • hidden: true means there's a validation error, but it's kept from the user's view.
  • hidden: false indicates that the validation error is actively being shown to the user.

In the example above, the message is hidden and only the text color is changed to red, highlighting that this field has a validation error.

In some cases, it's desired to show the validation error message to the user. For example, if the buyer tries to submit the checkout form without filling in the required fields. An example can seen when leaving the first name, last name and address fileds empty:

image

In WooCommerce Blocks, the following function handles the display logic of the validation error message:

export const ValidationInputError = ( {
	errorMessage = '',
	propertyName = '',
	elementId = '',
}: ValidationInputErrorProps ): JSX.Element | null => {
	const { validationError, validationErrorId } = useSelect( ( select ) => {
		const store = select( VALIDATION_STORE_KEY );
		return {
			validationError: store.getValidationError( propertyName ),
			validationErrorId: store.getValidationErrorId( elementId ),
		};
	} );

	if ( ! errorMessage || typeof errorMessage !== 'string' ) {
		if ( validationError?.message && ! validationError?.hidden ) {
			errorMessage = validationError.message;
		} else {
			return null;
		}
	}

	return (
		<div className="wc-block-components-validation-error" role="alert">
			<p id={ validationErrorId }>{ errorMessage }</p>
		</div>
	);
};

A simplified version of the code snippet above would be the following:

{
	validationError?.hidden === false && (
		<div className="wc-block-components-validation-error" role="alert">
			<p>{ validationError?.message }</p>
		</div>
	);
}

Actions

clearValidationError( errorId )

Clears a validation error.

Parameters

  • errorId string: The error ID to clear validation errors for.

Example

const store = dispatch( 'wc/store/validation' );
store.clearValidationError( 'billing-first-name' );

clearValidationErrors( errors )

Clears multiple validation errors at once. If no error IDs are passed, all validation errors will be cleared.

Parameters

  • errors string[] or undefined: The error IDs to clear validation errors for. This can be undefined, and if it is, all validation errors will be cleared.

Example

  1. This will clear only the validation errors passed in the array.
const store = dispatch( 'wc/store/validation' );
store.clearValidationErrors( [
	'billing-first-name',
	'billing-last-name',
	'terms-and-conditions',
] );
  1. This will clear all validation errors.
const store = dispatch( 'wc/store/validation' );
store.clearValidationErrors();

setValidationErrors( errors )

Sets the validation errors. The entries in errors will be added to the list of validation errors. Any entries that already exist in the list will be updated with the new values.

Parameters

  • errors object: The new validation errors, the keys of the object are the validation error IDs, and the values should be objects containing message string and hidden boolean.

Example

const { dispatch } = wp.data;
const { setValidationErrors } = dispatch( 'wc/store/validation' );

setValidationErrors( {
	'billing-first-name': {
		message: 'First name is required.',
		hidden: false,
	},
	'billing-last-name': {
		message: 'Last name is required.',
		hidden: false,
	},
} );

hideValidationError( errorId )

Hides a validation error by setting the hidden property to true. This will not clear it from the data store!

Parameters

  • errorId string: The error ID to hide.

Example

const { dispatch } = wp.data;
const { hideValidationError } = dispatch( 'wc/store/validation' );

hideValidationError( 'billing-first-name' );

showValidationError( errorId )

Shows a validation error by setting the hidden property to false.

Parameters

  • errorId string: The error ID to show.

Example

const { dispatch } = wp.data;
const { showValidationError } = dispatch( 'wc/store/validation' );

showValidationError( 'billing-first-name' );

showAllValidationErrors

Shows all validation errors by setting the hidden property to false.

Example

const { dispatch } = wp.data;
const { showAllValidationErrors } = dispatch( 'wc/store/validation' );

showAllValidationErrors();

Selectors

getValidationError( errorId )

Returns the validation error.

Parameters

  • errorId string: The error ID to get validation errors for.

Returns

  • object: The validation error which is an object containing message string and hidden boolean.

Example

const store = select( 'wc/store/validation' );
const billingFirstNameError = store.getValidationError( 'billing-first-name' );

getValidationErrorId( errorId )

Gets a validation error ID for use in HTML which can be used as a CSS selector, or to reference an error message. This will return the error ID prefixed with validate-error-, unless the validation error has hidden set to true, or the validation error does not exist in the store.

Parameters

  • errorId string: The error ID to get the validation error ID for.

Returns

  • string: The validation error ID for use in HTML.

Example

const store = select( 'wc/store/validation' );
const billingFirstNameErrorId =
	store.getValidationErrorId( 'billing-first-name' );

hasValidationErrors

Returns true if validation errors occurred, and false otherwise.

Returns

  • boolean: Whether validation errors occurred.

Example

const store = select( 'wc/store/validation' );
const hasValidationErrors = store.hasValidationErrors();

We're hiring! Come work with us!

🐞 Found a mistake, or have a suggestion? Leave feedback about this document here.