0
\$\begingroup\$

I have been working on recreating the WP columns block using server-side rendered blocks.

For the base creation of the block structure, I have used @wordpress/create-block --template es5. I believe I have got the overall operation working correctly but I am looking for input on how to improve the handling of conditionals and assigning variables, particularly in PHP.

An explanation of some of the block's controls in index.js

Column Select

Fairly self-explanatory here but this will control the number of columns, as well as determine when other controls are available.

Margin Select

A radio control that assigns set margin values via a modifier class. What is selected here determines if the double margins toggle is visible.

Double Margins

A toggle/boolean that is only visible when marginSelect is not equal to margins__none or margins__inContent. If this value is set to true it will add a modifier class.

Narrow Content

A simple toggle/boolean that will assign a modifier to make the content narrow. Visible in all states

Reverse Order on Mobile

Another toggle that will add a modifier called columns__reverse if true. Available in all states.

Offset Columns

Radio controls that add a modifier class depending on its selection. Only visible when columnSelect value is equal to 2.

//index.js
( function( wp ) {

    var registerBlockType = wp.blocks.registerBlockType;
    var el = wp.element.createElement;
    var __ = wp.i18n.__;

    const { useSelect } = wp.data;
    const { RangeControl, RadioControl, ToggleControl, PanelBody } = wp.components;
    const { useBlockProps, InnerBlocks, InspectorControls } = wp.blockEditor;
    const allowedBlocks = [ 'wpboiler-core/column' ];

    registerBlockType( 'wpboiler-core/columns', {

        apiVersion: 2,
        title: __(
            'Columns',
            'columns'
        ),
        description: __(
            'Displays content in columns',
            'columns'
        ),
        category: 'design',
        icon: 'schedule',
        supports: {
            html: false,
        },
        attributes: {
            columnselect: {
                type: 'number',
                default: 2,
            },
            marginSelect: {
                type: 'string',
                default: 'margins__inContent',
            },
            marginDouble: {
                type: 'boolean',
                default: false,
            },
            narrowContent: {
                type: 'boolean',
                default: false,
            },
            reverseOrder: {
                type: 'boolean',
                default: false,
            },
            columnOffset: {
                type: 'string',
                default: 'columns__offset--none'
            },
        },

        edit: function(props) {
            
            const { 
                attributes, 
                setAttributes, 
                clientId 
            } = props;

            const { 
                columnselect, 
                marginSelect,
                marginDouble,
                narrowContent,
                reverseOrder,
                columnOffset 
            } = attributes;

            const onChangeColumnSelect = value => setAttributes({ columnselect: value });
            const onChangeMarginSelect = value => setAttributes({ marginSelect: value });
            const onChangeMarginDoubleSelect = () => setAttributes({ marginDouble: marginDouble ? false : true });
            const onChangeNarrowContentSelect = () => setAttributes({ narrowContent: narrowContent ? false : true });
            const onChangeReverseOrderSelect = () => setAttributes({ reverseOrder: reverseOrder ? false : true });
            const onChangeOffsetSelect = value => setAttributes({ columnOffset: value });

            return el(
                'section',
                useBlockProps(attributes),
                __( 'Add columns by pressing the + icon. Maximum 4 columns', 'columns' ),

                // INSPECTOR CONTROLS BEGINS
                el(
                    InspectorControls,
                    null,

                    el(
                        PanelBody,
                        {
                            title: 'Columns Select',
                        },

                        el(
                            RangeControl, {
                                min: 2,
                                max: 4,
                                value: columnselect,
                                onChange: onChangeColumnSelect
                            }
                        ),
                    ),

                    el(
                        PanelBody, {
                            title: 'Margin Select'
                        },

                        el(
                            RadioControl,
                            {
                                selected: marginSelect,
                                options: [
                                    {
                                        label: 'No Margins',
                                        value: 'margins__none'
                                    },
                                    {
                                        label: 'Basic / In-content Margins',
                                        value: 'margins__inContent'
                                    },
                                    {
                                        label: 'Margins Top & Bottom',
                                        value: 'margins__topBottom'
                                    },
                                    {
                                        label: 'Top Margin Only',
                                        value: 'margins__top'
                                    },
                                    {
                                        label: 'Bottom Margin Only',
                                        value: 'margins__bottom'
                                    },
                                ],
                                onChange: onChangeMarginSelect
                            }
                        ),

                        (marginSelect !== 'margins__none' ? 
        
                            (marginSelect !== 'margins__inContent' ? el(
                                ToggleControl,
                                {
                                    label: 'Double Margins?',
                                    checked: marginDouble,
                                    onChange: onChangeMarginDoubleSelect
                                }
                            ) : null) 
                            
                        : null),
                        
                    ),

                    el(
                        PanelBody, {
                            title: 'Styling Controls'
                        },

                        el(
                            ToggleControl, 
                            {
                                label: 'Narrow content?',
                                help: 'Sets the column width to match narrow text content.',
                                checked: narrowContent,
                                onChange: onChangeNarrowContentSelect
                            }
                        ),

                        el(
                            ToggleControl,
                            {
                                label: 'Reverse order on mobile?',
                                help: 'When on mobile devices the order of stacked items will be reversed.',
                                checked: reverseOrder,
                                onChange: onChangeReverseOrderSelect
                            }
                        ),

                        (columnselect === 2 ? el(
                            RadioControl,
                            {
                                label: 'Offset columns?',
                                help: 'For a design choice, the columns can be offset. This option is only available for 2 column layouts.',
                                selected: columnOffset,
                                options: [
                                    {
                                        label: 'No offset',
                                        value: 'columns__offset--none',
                                    },
                                    {
                                        label: '60 / 40',
                                        value: 'columns__offset--6040',
                                    },
                                    {
                                        label: '40 / 60',
                                        value: 'columns__offset--4060',
                                    },
                                ],
                                onChange: onChangeOffsetSelect
                            }
                        ) : null),

                        
                    ),
                ),
                // INSPECTOR CONTROLS END

                // PREVIEW AREA BEGIN
                el(
                    'div',
                    { className: 'columns__container' },

                    el(
                        InnerBlocks, {
                            allowedBlocks: allowedBlocks,
                        }
                    )
                        
                ),
                // PREVIEW AREA END
            );
        },

        save: function() {  
            return el(InnerBlocks.Content, {});
        },
    } );
}(
    window.wp
) );

An explanation of columns.php

I am assigning variables based on attributes passed from index.php. These variables are being pushed to an array called $classes and then echoed in the markup. Some of these have default values, and others are only assigned if certain conditions are met - to prevent unused classes/modifiers being added to the markup. I think it is here where I would look for some input and how this can be improved.

// columns.php
function wpboiler_columns_block_init() {
    $dir = get_template_directory() . '/gutenberg';

    $index_js = 'columns/index.js';
    wp_register_script(
        'wpboiler-columns-block-editor',
        get_template_directory_uri() . "/gutenberg/$index_js",
        array(
            'wp-block-editor',
            'wp-blocks',
            'wp-i18n',
            'wp-element',
        ),
        filemtime( "$dir/$index_js" )
    );
    wp_set_script_translations( 'wpboiler-columns-block-editor', 'columns' );

    $editor_css = 'columns/editor.css';
    wp_register_style(
        'wpboiler-columns-block-editor',
        get_template_directory_uri() . "/gutenberg/$editor_css",
        array(),
        filemtime( "$dir/$editor_css" )
    );

    $style_css = 'columns/style.css';
    wp_register_style(
        'wpboiler-columns-block',
        get_template_directory_uri() . "/gutenberg/$style_css",
        array(),
        filemtime( "$dir/$style_css" )
    );

    register_block_type(
        'wpboiler/columns',
        array(
            'editor_script'     => 'wpboiler-columns-block-editor',
            'editor_style'      => 'wpboiler-columns-block-editor',
            'style'             => 'wpboiler-columns-block',
            'render_callback'   => 'wpboiler_core_columns_render'
        )
    );
}
add_action( 'init', 'wpboiler_columns_block_init' );

function wpboiler_core_columns_render( $attr, $content ) {
    $html = '';

    $classes = array();

    $classes[] = $colCount = (isset($attr['columnselect']) ? 'columns__count--' . $attr['columnselect'] : 'columns__count--2');
    $classes[] = $margins = (isset($attr['marginSelect']) ? $attr['marginSelect'] : 'margins__inContent');
    $classes[] = $narrowContent = (isset($attr['narrowContent']) ? 'content__narrow' : '');
    $classes[] = $reverseOrder = (isset($attr['reverseOrder']) ? 'columns__reverse' : '');

    if($margins != 'margins__inContent' && $margins != 'margins__none' && isset($attr['marginDouble'])) {
        $marginDouble = 'margins__double';
        $classes[] = $marginDouble;
    }
    
    if($colCount == 'columns__count--2' && isset($attr['columnOffset'])) {
        $columnOffset = $attr['columnOffset'];
        $classes[] = $columnOffset;
    }

    $html = '<section class="columns ' . implode(" ", $classes) . '">
                <div class="columns__container">
                    ' . $content . '
                </div>
            </section>';

    return $html;
}

What help am I looking for?

I think in general some guidance on improving handling of conditional rendering, both in PHP and JS, as well as handling boolean values.

\$\endgroup\$
2
  • \$\begingroup\$ Do you know which version of PHP is running on the server(s)? \$\endgroup\$ Nov 9 at 0:07
  • \$\begingroup\$ At the moment it's a local development running 7.3.5. I have been using this in work environments that are defaulted as low as 7 (Seeing that information has made me think that probably needs to be changed). \$\endgroup\$
    – Bagseye
    Nov 9 at 8:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.