3

The goal

I'm working on a plugin that adds classes and attributes to any block.

On the frontend the blocks are animated using JS and CSS.

It basically works, but...

It seemed to be working fine with all blocks (haven't tested all), but when I added a "Tag Cloud" block to a page I got the following 400 error:

enter image description here

In the console I found the params Object { attributes: "blockAnimationClass is not a valid property of Object." } response.

I use the following filter to add the properties:

function addAnimationOptions(settings, name) {
    if (typeof settings.attributes !== 'undefined') {
        settings.attributes = Object.assign(settings.attributes, {
            blockAnimationClass: {
                type: 'string',
                default: ''
            }
        });
    }
    return settings;
}
    
wp.hooks.addFilter(
    'blocks.registerBlockType',
    'ekesto/add-animation-options',
    addAnimationOptions
);

In the InspectorControls sidebar I have a SelectControl that contains class names that I add to the save function via the blocks.getSaveContent.extraProps filter:

function animationOptionsApplyExtraClass(extraProps, blockType, attributes) {
    const { blockAnimationClass } = attributes;
    if (typeof blockAnimationClass !== '' && blockAnimationClass) {
        let children_classes = '';
        switch(blockAnimationClass) {
            case 'anim-slide-children-up':
                children_classes = 'anim-slide-up';
                break;
            default:
                children_classes = '';
                extraProps.className = extraProps.className + ' animation-observer ' + blockAnimationClass;
        }
        // if a children animation is selected, add classes
        if (children_classes != '') {           
            children_classes += ' animation-observer';
            extraProps['data-anim-children'] = children_classes.trim();
        }
    }
    return extraProps;
}
    
wp.hooks.addFilter(
    'blocks.getSaveContent.extraProps',
    'ekesto/animation-options-apply-class',
    animationOptionsApplyExtraClass
);

Question

In what way is the Tag Cloud block different?

Am I doing some no-go stuff here, or what detail am I missing?

Is it linked to the issue that my attributes are not available when the block is rendered first? If so, is there a filter that adds the attributes at an earlier stage?

Appreciate any hint!

2
  • 1
    the error message is telling you that the tag cloud does not have an attribute of that name, but it found one, so something must be wrong. Eitherway this isn't the approach you should take, blocks already have a class attribute that can be used for this so adding an additional attribute is unnecessary.
    – Tom J Nowell
    Feb 29 at 15:10
  • Thanks for your feedback! I store the classes into the default className property, besides the optional extraProps['data-anim-children'] property that is being used as a data attribute that is handled using JS.. Sally's suggestion removed the error..
    – beat
    Mar 1 at 19:40

1 Answer 1

1

In what way is the Tag Cloud block different?

That block is a dynamic block, which uses a live rendering using ServerSideRender, and the documentation stated that "If you pass attributes to ServerSideRender, the block must also be registered and have its attributes defined in PHP", therefore, custom attributes for the block must be defined in PHP as well and not just JavaScript.

To fix the issue, you can use the register_block_type_args filter to add the blockAnimationClass attribute. E.g.

add_filter( 'register_block_type_args', 'my_add_custom_block_type_attributes' );
function my_add_custom_block_type_attributes( $args ) {
    $args['attributes']['blockAnimationClass'] = array(
        'type'    => 'string',
        'default' => '',
    );

    return $args;
}
6
  • Thank you so much, that makes perfect sense.. I managed to get rid of the error by using the filter. This answered my question!
    – beat
    Mar 1 at 19:53
  • 1
    They're not saved because it's a dynamic block which does not add anything to the post content, apart from the block comment delimiter markup. So I'd use editor.BlockEdit and not blocks.getSaveContent.extraProps, to modify the className attribute. As for the data-anim-children prop though, is it actually necessary, i.e. can't you just modify the block content/markup based on the blockAnimationClass value? But if it's necessary, then (for dynamic blocks with a render_callback) you can use the PHP filter hook to add that data attribute.
    – Sally CJ
    Mar 2 at 7:05
  • 1
    "to modify the block content/markup" - or more precisely, to apply the animation based on the element's classes. And if this is a JS-based animation, then you can use JS on the front-end to add the data attribute?
    – Sally CJ
    Mar 2 at 7:16
  • 1
    Thanks for your time and energy! Your inputs lead to some more research and I optimized my code. I'm now setting the class into the official className attribute - where it belongs. And the data attribute is now set in the render_block hook, as disabling the plugin would lead to block recovery issues when they're stored as an extraProps (like I did before). After oh so many block tutorials the bigger picture is slowly put together in my brain :) Piece by piece.. Thanks again!
    – beat
    Mar 3 at 21:35
  • 1
    Yep, I would simply modify the className attribute, but I posted this answer basically just so that you know what happened 😉 anyway, happy coding and all the best!
    – Sally CJ
    Mar 4 at 12:19

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.