Add Select2 as an InspectorControl in WordPress Gutenberg

·

For a project I was working on I wanted to use Select2 as a Gutenberg InpectorControl to allow me apply settings to a block. This tutorial will also give you the foundation you need for getting any third party React Component into the WordPress Gutenberg Editor.

Select2 is a super handy replacement for select boxes on your website. In particular it has some great options for selecting multiple items.

The finished product, Select2 in the WordPress Gutenberg InspectorControls

The finished product, Select2 in the WordPress Gutenberg InspectorControls

The good news is that I didn’t need to build a React component to get Select2 into Gutenberg, the react-select component by Jed Watson, already does a great job of this, however getting it to play nice with Gutenberg was not as easy as just following the instructions.

First things first, we needed to install the component into our build. As this was on npm it was as simple as entering the following into our terminal:

npm install react-select --save

Getting Select2 into a Gutenberg Block

Using Zac Gordons Gutenberg Course Git repo (part of Zac Gordons fantastic Gutenberg development course) as a base for my plugin (in particular the InspectorControls example), to use react-select I needed to add the following includes at the top of my file:

import React from 'react';
import Select from 'react-select';

Oh no! Compiling this gives us an error:

Module not found: Error: Can’t resolve ‘react’

Never fear, this great article on “How to use external React components in your Gutenberg blocks” by CSS Igniter came to the rescue, all we need to do is register externals in our webpack.config.js file:

externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
}

Like so:

module.exports = {
    entry: {
        './assets/js/editor' : './blocks/index.js',
        './assets/js/script' : './blocks/script.js',
    },
    output: {
        path: path.resolve( __dirname ),
        filename: '[name].js',
    },
    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM',
    }
...

Registering the InspectorControls

Inside the panel roll of your <InspectorControls> component you will need to add the following:

<Select
    name='select-two'
    value={ JSON.parse( selectedOption ) }
    onChange={ handleSelectChange }
    options={[
        { value: 'health', label: 'Health' },
        { value: 'wealth', label: 'Wealth' },
        { value: 'code', label: 'Code' },
    ]}
    isMulti='true'
    />

We are not quite done, as we will also need to register the selectedOption attribute and handleSelectChange function. We can do this like so:

attributes: {
    selectedOption: {
        type: 'string',
        default: null,
    }
},

…and now for the function…

const handleSelectChange = ( selectedOption ) => setAttributes( { selectedOption: JSON.stringify( selectedOption ) } );

Hang on, why do we need to JSON.stringify() and JSON.parse() the values? Well, because the value that the react-select component accepts is an array, and as Gutenberg wont let us save this value as an array, this is a workaround we can use.

Putting it Together

Our complete InspectorControls area should now look like so:

...
attributes: {
    selectedOption: {
        type: 'string',
        default: null,
    }
},
edit: props => {
    const { attributes: { selectedOption }, className, setAttributes } = props;
    const handleSelectChange = ( selectedOption ) => setAttributes( { selectedOption: JSON.stringify( selectedOption ) } );
    return [
        <InspectorControls>
            <PanelBody
                title={ __( 'Select2', 'text-domain' ) }
            >
                <PanelRow>
                    <Select
                        name='select-two'
                        value={ JSON.parse( selectedOption ) }
                        onChange={ handleSelectChange }
                        options={[
                            { value: 'health', label: 'Health' },
                            { value: 'wealth', label: 'Wealth' },
                            { value: 'code', label: 'Code' },
                        ]}
            isMulti='true'
                        />
                 </PanelRow>
             </PanelBody>
         </InspectorControls>,
...

Looking Good in Gutenberg

As you can see by the screenshot, it works pretty well:

Select2 as a Gutenberg InspectorControl

Select2 as a Gutenberg InspectorControl

Taking it Further

I used this Inspector Control in my Secure Blocks for Gutenberg plugin, find out how I populated the Select2 control with dynamic data from the WordPress REST API.