React validation with a Gutenberg block

2019-08-26 02:14发布

问题:

I have built a Gutenberg plugin with a few custom fields. Now I want these custom fields to be validated when I hit Publish or Update button.

I was reading https://github.com/jxnblk/react-validate-hoc. But since I am very new to Gutenberg development, finding it hard to understand how to incorporate it with my custom block. Moreover, the validation fires according to this example on onBlur event. Isn't there a way to hook the validation on Save event?

I am using create-guten-block tool to create my block.

Is there any complete guide available which explains the entire process step by step?

Here is my block:

/**
 * BLOCK: Book Metadata
 *
 * Registering a dynamic block with Gutenberg.
 * Renders a block with to store metadata about a book in wp_postmeta table.
 */

//  Import CSS.
import './style.scss';
import './editor.scss';

const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
const {
    PlainText,
    InspectorControls,
    BlockControls,
} = wp.editor;
const {
    PanelBody,
    TextareaControl,
    TextControl,
    Dashicon,
    Toolbar,
    Button,
    Tooltip,
} = wp.components;

registerBlockType( 'book-list/book-metadata-block', {
    title: __( 'About Book' ),
    icon: 'book',
    category: 'common',
    keywords: [
        __( 'Book' ),
        __( 'Book information' )
    ],
    attributes: {
        author: {
            type: 'string',
            source: 'meta',
            meta: 'book_author',
        },
        publisher: {
            type: 'string',
            source: 'meta',
            meta: 'book_publisher',
        },
        synopsis: {
            type: 'string',
            source: 'meta',
            meta: 'book_synopsis',
        },
        language: {
            type: 'string',
            source: 'meta',
            meta: 'book_language',
        },
        pub_year: {
            type: 'string',
            source: 'meta',
            meta: 'book_year',
        },

        price: {
            type: 'string',
            source: 'meta',
            meta: 'book_price',
        },

        discount: {
            type: 'string',
            source: 'meta',
            meta: 'book_discount',
        },

        pages: {
            type: 'string',
            source: 'meta',
            meta: 'book_pages',
        }
    },
    edit: function( props ) {
        function onAuthorChange( thisValue ) {
            props.setAttributes( { author: thisValue } );
        }

        function onPublisherChange( thisValue ) {
            props.setAttributes( { publisher: thisValue } );
        }

        function onSynopsisChange( thisValue ) {
            props.setAttributes( { synopsis: thisValue } );
        }

        function onLanguageChange( thisValue ) {
            props.setAttributes( { language: thisValue } );
        }

        function onYearChange( thisValue ) {
            props.setAttributes( { pub_year: thisValue } );
        }

        function onPriceChange( thisValue ) {
            props.setAttributes( { price: thisValue } );
        }

        function onDiscountChange( thisValue ) {
            props.setAttributes( { discount: thisValue } );
        }

        function onPagesChange( thisValue ) {
            props.setAttributes( { pages: thisValue } );
        }


        return(
            <div id="book-metadata">

                <InspectorControls key="inspector">
                    <PanelBody title={ __('Pricing') }>
                        <TextControl
                            label={ __( 'Printed Price' ) }
                            placeholder={ __( 'Original Price' ) }
                            value={ props.attributes.price }
                            onChange={ onPriceChange }
                            maxLength="15"
                        />
                        <TextControl
                            label={ __( 'Discount (%)' ) }
                            placeholder={ __( 'Discount in percent' ) }
                            value={ props.attributes.discount }
                            onChange={ onDiscountChange }
                            maxLength="6"
                        />
                    </PanelBody>
                    <PanelBody title={ __('Publication') }>
                        <TextControl
                            label={ __( 'Publisher' ) }
                            value={ props.attributes.publisher }
                            onChange={ onPublisherChange }
                            maxLength="35"
                        />
                        <TextControl
                            label={ __( 'Year of Publication' ) }
                            value={ props.attributes.pub_year }
                            onChange={ onYearChange }
                            maxLength="4"
                        />
                    </PanelBody>
                    <PanelBody title={ __('Language and others') }>
                        <TextControl
                            label={ __( 'Language' ) }
                            value={ props.attributes.language }
                            onChange={ onLanguageChange }
                            maxLength="35"
                        />
                        <TextControl
                            label={ __( 'No. of Pages' ) }
                            value={ props.attributes.pages }
                            onChange={ onPagesChange }
                            maxLength="4"
                        />
                    </PanelBody>
                </InspectorControls>

                <h3>About the book</h3>
                <div className="book-author">
                    <label>Author</label>
                    <PlainText
                        placeholder={ __( 'Book author' ) }
                        value={ props.attributes.author || '' }
                        onChange={ onAuthorChange }
                        maxLength="50"
                    />
                </div>
                <div className="book-synopsis">
                    <label>Brief</label>
                    <PlainText
                        placeholder={ __( 'A brief about this book within 1000 characters' ) }
                        value={ props.attributes.synopsis || '' }
                        onChange={ onSynopsisChange }
                        aria-multiline="true"
                        rows="6"
                        columns="30"
                        maxLength="1000"
                    />
                </div>
            </div>
        );
    },
    save: function( props ) {
        return null;
    }
} );