Wonderful! WordPress

Gutenberg Block Editor 自作その3 - form編

Page No.3

Selectable paragraph or span or label tag block

※2024年1月10日追記

このブロックに関しては、現在ではもう使用していないので、ちゃんと動くかどうか未確認。以前は、これで機能していたということの参考だけにしてください。

*
*
*
*
*
*
*
*

同じように子要素として RichText を使えば良さそうなブロックなわけで、タグを選択式にしてやるだけのことなので、簡単にできそうではあったのだけれど・・・、そうはなかなか。

何においてなかなかうまくいかなかったかというと、InnerBlocks とは違い、子要素のテキストを保存しておかなければいけないので、attributes content 指定が重要になってくる。その場合の、contentselector の指定でつまづいてしまったというわけ。タグを選択式にするということは、この content.selector の値も変更してやらないとだめだろうと思い、そのあたりで四苦八苦してしまったわけ。ただ、これは変更して良いものか否か、変更できているのかいないのか、どうにもうまくいかず、varidation error が出てしまう。

と、ふと、標準装備の H1 などの heading タグを思い出した。このブロックは H1H2 とそのレベルを選択できるようになっているよな、と。さっそく調べてみると、GitHub にその答えがあった。
実に簡単なことで、その selector に選択肢となる可能性のあるものを、”,” で列挙して指定すればいいだけのことであった。

( function ( blocks, element, blockEditor, components ) {
	const el = element.createElement,
        Fragment = element.Fragment,
        InspectorControls = blockEditor.InspectorControls,
        TextControl = components.TextControl,
		useBlockProps = blockEditor.useBlockProps,
        RichText = blockEditor.RichText;

    blocks.registerBlockType( 'stx-selectable-spl/selectable-spl', {
        title: 'STX selectable spl',
        icon: 'smiley',
        category: 'design',
        description: 'Selectable Paragraph or Span or Label tag',

        attributes: {
            wrapper: { type: 'string', default: 'p' },
            lblfor: { type: 'string', default: '' },
            content: { type: 'array', source: 'children', selector: 'p,span,label' },
            anchor: { type: 'string' },
        },

        supports: {
            anchor: true,
            // className: false, 
        },

        edit: function( props ) {

            let blockProps = useBlockProps(),
                { wrapper, lblfor, content } = props.attributes,
                elem = {
                    tagName: wrapper,
                    className: props.className,
                    onChange: ( newContent ) => { props.setAttributes( { content: newContent } ) },
                    value: content
                };

            if ( 'label' === wrapper ) {
                elem['htmlFor'] = lblfor;
            }

            return(
                el(
                    Fragment,
                    null,
                    el(
                        InspectorControls,
                        null,
                        el( 'div', { id: 'stx_iddiv_sdbr', style: { fontSize: '1.3em' } },
                            el(
                                SelectControl,
                                {
                                    label: 'Select Tag',
                                    value: wrapper,
                                    options: [
                                        { value: 'p', label: 'p' },
                                        { value: 'span', label: 'span' },
                                        { value: 'label', label: 'label' }
                                    ],
                                    onChange: function( newValue ){ props.setAttributes( { wrapper: newValue } ); }
                                }
                            ),
                            el(
                                TextControl,
                                {
                                    label: 'lable タグの for 属性',
                                    value: lblfor,
                                    onChange: function( newValue ){ props.setAttributes( { lblfor: newValue } ); }
                                }
                            ),
                        ),
                    ),
                    el( RichText, Object.assign( blockProps, elem ) )
                )
            );
        },

        save: function( props ) {
            let { wrapper, lblfor, content } = props.attributes,
                elem = { tagName: wrapper, className: props.className, value: content },
                blockProps = useBlockProps.save();

            if ( props.attributes.anchor ) {
                blockProps.id = props.attributes.anchor;
            }
            if ( 'label' === wrapper ) {
                elem['htmlFor'] = lblfor;
            }

            return el( RichText.Content, Object.assign( blockProps, elem ) );
        },
    });
}(
    window.wp.blocks,
    window.wp.element,
    window.wp.blockEditor,
    window.wp.components,
) );
JavaScript
CopyExpand

checkbox はフォームの要素としてではなく、例えばサイドバーを出したり消したりするのに、checkbox の check 状況でその弟要素を css にて操作するということをよく使用するということもあって、label + checkbox はそれぞれ単独で使用できるブロックというのは必要だったわけなんだけれど、これでほぼ、必要なものは揃ったという感じかな。
と、いうことで以上です。

Sanbanse Funabashi
2011.01.01 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。