3

I build a small TOC plugin with a ServerSideRender component. It's an open-source hobby project to understand Gutenberg better: https://wordpress.org/plugins/simpletoc/ Now I would like to add attributes to the block to toggle options like "disable title". A few months ago with your help here I managed to make the plugin work, but it sends "fake attributes". In my case, this is only a date.

My understanding of ServerSideRender is that the plugin get its contents from the php part via ajax. But attributes are saved in the markup. Source: https://developer.wordpress.org/block-editor/tutorials/block-tutorial/introducing-attributes-and-editable-fields/ But since my plugin does not generate the markup via js but via php is it still possible to add custom attributes?

Here is the block part with the "send fake attributes" function that works:

function sendfakeAttribute(props) {
  // this acuallty triggers the ServerSideRender again ¯\_(ツ)_/¯
  props.setAttributes({ updated: Date.now()});
}

registerBlockType('simpletoc/toc', {
  title: __('SimpleTOC', 'simpletoc'),
  icon: simpletocicon,
  category: 'layout',
  edit: function(props) {
    return [
      el(
        BlockControls, { key: 'controls' },
        el( Toolbar, null,
          el(
            IconButton, {
              className: 'components-icon-button components-toolbar__control',
              label: __('Update table of contents', 'simpletoc'),
              onClick: function() {
                sendfakeAttribute(props)
              },
              icon: 'update'
            }
          )
        )
      ),
      el(
        'p', { className: props.className },
        el(
          ServerSideRender, {
            block: props.name,
            attributes: props.attributes
          }
        )
      )
    ];
  },
  save: props => {
    return null;
  },
});

But when I add this below registerBlockType how does it save the values? Am I stuck by using SSR? Or is the selector something like <serversiderender> in the attributes section here.

registerBlockType('simpletoc/toc', {
  title: __('SimpleTOC', 'simpletoc'),
  icon: simpletocicon,
  attributes: {
      disabletitle: {
          type: 'boolean',
          source: 'children',
          selector: 'serversiderender'
      }
  },
  category: 'layout',
  edit: function(props) {

1 Answer 1

3

Yes, and it works exactly the same as any other block, no fake attributes are necessary. When the JS needs to display the component it will make the AJAX request to fetch the markup and pass the attributes with it.

The important part to note is that a block in the block editor is still JS. We're just generating some HTML with PHP.

When the post is saved, that HTML comment markup with the attributes is still saved, it's the block editor that generates that markup, not your PHP or JS block implementation. Because your save function is empty though, it'll just be the HTML comment with the attributes.

Likewise, your fake attribute can be eliminated by using useSelect() to read the block editor data store, and in turn eliminating the need for an update TOC button.

Additionally, even though your block is a dynamic PHP rendered block, that doesn't mean that your edit function needs to be server rendered. It can be entirely JS, it can be both JS and server rendered ( there is a server render component ), it could even be a picture of a cat with no relation to what gets saved. The edit function returns the interactive editor UI, and the save function returns what actually gets stored in the database. The block editor then serializes this to a string and wraps it in the appropriate markup or JSON intermediary for whatever purpose is needed.

1
  • Thank you Tom. I will look into useSelect right away! And I know that I could do it somehow with js. Maybe you remember because I tried that and asked too many questions here and gave up. =) But it's 2021 and I am on holiday and am eager to learn. import { useSelect, AsyncModeProvider } from '@wordpress/data';
    – Marc
    Commented Jan 6, 2021 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.