如何在Guttenberg的RegisterFormatType方法中存储、检索和写入属性?

时间:2020-10-18 作者:pseudoCK

我正在尝试将具有多个独立属性的格式添加到自定义<a> 标签属性为href=data-caption=data-set= 而我使用自定义客户端JavaScript来处理数据属性。

这是我的劣质、正在进行的代码:

    var el = wp.element.createElement;
    var components = wp.components;

    var withSelect  = wp.data.withSelect;
    var ifCondition = wp.compose.ifCondition;
    var compose     = wp.compose.compose;

    var caption;
    var setName;

    wp.richText.registerFormatType(
        \'test/set-link\',
        {
            attributes: {
                url: \'href\',
                caption: \'data-caption\',
                setName: \'data-set\',
            },
            title: \'Sets Link\',
            tagName: \'a\',
            className: \'sets-link\',
            edit: (props) => {
                var attributes = props.attributes; // console declares this as undefined.
                return [
                    el(wp.blockEditor.RichTextToolbarButton, {
                        icon: \'block-default\',
                        title: __(\'Sets Link\'),
                        isActive: true,
                        onClick: () => {
                            props.onChange(
                                wp.richText.toggleFormat( props.value, {
                                    type: \'test/sets-link\'
                                })
                            )           
                        }
                    }),
                    props.isActive && ( el( components.Popover, 
                        {
                            position: \'bottom center\',
                            headerTitle: \'Sets Attributes\',
                        }, 
                        [
                            el( components.TextControl, {
                                placeholder: \'Set Name\',
                                value: attributes.setName,
                                onChange:  (newSetName) => {
                                    props.setAttributes( { setName: newSetName } 
 ) // TypeError: can\'t access property "setName", attributes is undefined
                                },
                            }),
                            el( components.TextControl, {
                                placeholder: \'Set Caption\',
                                value: attributes.caption,
                                onChange: (newCaption) => {
                                    props.setAttributes( { caption: newCaption } ) // TypeError: can\'t access property "setName", attributes is undefined
                                }
                            }),
                            el( components.Button, {
                                className: \'button button-large\',
                                onClick: () => {
                                    //TODO: here
                                }

                            },
                                \'Set\'
                            )
                        ]
                    )),
                    compose(
                        withSelect( ( select ) => {
                            return {
                                selectBlock: select( \'core/block-editor\' ).getSelectedBlock()
                            }
                        } ),
                        ifCondition( ( props ) => {
                            return(
                                props.selectBlock
                            )
                        } )
                    )
                ]
            },
        }
    )
嗯,令人惊讶的是,它在很大程度上发挥了作用。弹出窗口似乎接受输入,但无法将其存储在内存中。其次,它如何将存储的属性导出为输出属性。

我知道使用registerBlockType方法会更容易,定义也更明确,但我不使用它的原因是自定义链接,<a> 标记,可能会与Guttenberg编辑器的剩余RichText混合在一起。

我真的很感谢你在这个有趣的难题上的帮助。

1 个回复
最合适的回答,由SO网友:Tom J Nowell 整理而成

所以内联格式本身没有状态,它们不是块之类的离散对象。相反,您可以将一种格式应用于文本片段,并动态生成UI。

然后为该UI指定当前处于活动状态的属性activeAttributes 传递包含这些属性的数组。注意:仅传递活动属性。如果只对文本应用格式,则尚未设置任何属性,因此此数组将为空。因此,您不能依赖属性始终存在或具有默认值。

当您想要更改或添加这些属性时,您不能只更新或设置它们,相反,您需要调用applyFormat 使用值(在props中可用),指定要应用的格式和属性的完整列表(不更新,会覆盖)。那你需要打电话onChange 使用新值applyFormat 之后返回。

下面是一个将您的精简为name 属性:

wp.richText.registerFormatType(
    \'test/set-link\',
    {
        attributes: {
            name: \'data-set\',
        },
        title: \'Sets Link\',
        tagName: \'a\',
        className: \'sets-link\',
        edit: (props) => {
            return [
                el(wp.blockEditor.RichTextToolbarButton, {
                    icon: \'block-default\',
                    title: \'Sets Link\',
                    isActive: props.isActive,
                    onClick: () => {
                        props.onChange(
                            wp.richText.toggleFormat( props.value, {
                                type: \'test/set-link\'
                            })
                        )
                    }
                }),
                props.isActive && ( el( components.Popover,
                    {
                        position: \'bottom center\',
                        headerTitle: \'Sets Attributes\',
                    },
                    [
                        el( components.TextControl, {
                            placeholder: \'Set Name\',
                            value: props.activeAttributes.name ? props.activeAttributes.name : \'\',
                            onChange:  (newName) => {
                                newval = wp.richText.applyFormat(
                                    props.value,
                                    {
                                        type: \'test/set-link\',
                                        attributes: {
                                            name: newName
                                        }
                                    }
                                );
                                props.onChange( newval );
                            },
                        }),
                    ]
                ))
            ]
        },
    }
)
请注意,如果使用WP脚本工具,它会小得多,这将允许您直接使用JSX/React,而无需捆绑库。

我还修复了一个拼写错误和一个bugisActive 在工具栏按钮上始终设置为true

相关推荐

render html no formatting

如何让WordPress在不添加任何附加html的情况下呈现页面?我正在尝试构建一个可以在移动设备上运行的对话框,我只想显示该对话框,而不想在其周围显示任何标准的wordpress内容。