'Wordpress Gutenberg Anchor Support for Dynamic Block

I want to have anchor support for my dynamic wordpress block. I did

//in registerBlockType
supports: {
    anchor: true,
},

This adds the HTML Anchor control under the sidebar panel.

My block is a dynamic block that has

save: ( props ) => {
  return <InnerBlocks.Content />;
}

I tried everything to get the anchor attribute to to frontend. According to this github issue I should add

anchor: { 
    type: 'string', 
    source: 'attribute', 
    attribute: 'id', 
    selector: '*', 
}, 

to the blocks attributes. This will make the anchor available in the save function via props.anchor, however it never appears in my render_callback $attributes.

This is basically a port of the github issue to SO. Hope anyone can help here.



Solution 1:[1]

if anyone is still interested this worked for me:

so this is my custom block registering, this statement will enable standard wordpress HTML anchor field (with valuable validation for spaces etc.) under Advanced tab of selected gutenberg block:

supports: {
  anchor: true
}

then in the same place we define:

attributes: {
  anchor: {
    type: 'string'
  }
}

then in save function (I have it exactly for the same purpose of InnerBlocks):

save: function(props) {
  const { anchor } = props.attributes;
  return (
    el( anchor, {}),
    el( InnerBlocks.Content, {})
  );
}

if you are using jsx, the save function could look like this:

save: function(props) {
  const { anchor } = props.attributes;
  return (
    <div id={anchor}>
      <InnerBlocks.Content />
    </div>
  );
}

then in your render callback function (in php) it's going to be available via first arg's (which is array) element

function your_callback( $block, $content ) {
  // display your anchor value
  echo $block['anchor'];
}


Solution 2:[2]

Have you tried manually adding a field that will take care of the ID attribute?

Something like this:

<InspectorControls>
    <PanelBody title={ __( 'Element Settings' ) }>
        <TextControl
            label={ __( 'Element ID', 'fleximpleblocks' ) }
            value={ elementID}
            placeholder={ __( 'Type in the element ID…' ) }
            onChange={ ( value ) => setAttributes( { elementID: value } ) }
        />
    </PanelBody>
</InspectorControls>

And then:

save: ( props ) => {
    return <InnerBlocks.Content id={ props.attributes.elementID } />;
}

I'm not sure if it'll work, I'm just taking a wild guess here. Let me know how it goes :)

Solution 3:[3]

You could use this filter (targeting whatever blocks you want)

const withAnchor = props => {
  if (props.attributes) { // Some blocks don't have attributes
    props.attributes = {
      ...props.attributes,
      anchor: {
        type: 'string'
      }
    }
  }
  return props
}

wp.hooks.addFilter(
  'blocks.registerBlockType',
  'namespace/with-anchor',
  withAnchor
)

And then you can access the 'anchor' attribute in the render callback

'render_callback' => function($attributes) {
  echo $attributes['anchor'];
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 honk31
Solution 2 Rodrigo D'Agostino
Solution 3 Rice_Crisp