Support

Account

Home Forums Gutenberg Conditional to check if an instance of a block is the first on page/post

Solved

Conditional to check if an instance of a block is the first on page/post

  • I have made a cover block with a full size background image and text on top. If this block is inserted as the very first block on a page/post, I wan’t it to display the cover title in <h1> instead of <h2>, so that it acts as a hero block.

    This guy made exactly the same question: https://wordpress.stackexchange.com/questions/349050/gutenberg-first-block-on-page-conditional

    His code is great, but as he says, if there are more instances of the same block, the changes in his conditional would be made to all of them, and not just the very first instance.

    So how can I check if a block is the first on a post/page, and make a change to only that instance?

  • Here’s a solution I’ve come up with, that works with WordPress 5.4 and ACF Pro 5.8.9.

    First you need this function somewhere in functions.php:

    /**
     * Get ID of the first ACF block on the page
     */
    function sg_get_first_block_id() {
        $post = get_post(); 
    
        if(has_blocks($post->post_content)) {
            $blocks = parse_blocks($post->post_content);
            $first_block_attrs = $blocks[0]['attrs'];
    
            if(array_key_exists('id', $first_block_attrs)) {
                return $first_block_attrs['id'];
            }
        }
    }

    This function is used to get the block id of the first block on the page, if this block has a block id. (As far as I can see only ACF blocks have a block id attribute. Core blocks do not).

    Now in your block template file you can do this:

    <?php if($block['id'] === sg_get_first_block_id()): ?>
        <h1><?php the_title(); ?></h1>
    <?php endif; ?>

    $block['id'] is the unique id of every block instance. We then compare it with the id of the first block on the page. If they’re the same, the function will return true, and the title of the post will be displayed.

    How i use it
    I have created a custom cover block with a full size background image and content inside. I wan’t that block to act as a hero element if it’s the very first block on a page.

    By using the above method in my block template file, I can display the custom cover block title in a h1 tag instead of h2, if it’s the first block on the page.

    <?php if($block['id'] === sg_get_first_block_id()): ?>
        <h1><?php echo $title; ?></h1>
    <?php else: ?>
        <h2><?php echo $title; ?></h2>
    <?php endif; ?>

    I also wan’t to hide the ordinary title and breadcrumb, so that the cover block aligns perfectly to the navigation header. For that I have created this function in my functions.php file:

    /**
     * Check first block type
     * @param string block_handle - handle of the block
     */
    function sg_first_block_is($block_handle) {
        $post = get_post(); 
    
        if(has_blocks($post->post_content)) {
            $blocks = parse_blocks($post->post_content);
    
            if($blocks[0]['blockName'] === $block_handle) {
                return true;
            }else {
                return false;
            }
        }
    }

    I can use this as a conditional to check what block type the first block is, and then display or hide the breadcrumb and title accordingly:

    if(!sg_first_block_is('acf/sg-cover')):
        get_template_part('template-parts/components/component', 'breadcrumbs'); 
        echo '<h1>' . get_the_title() . '</h1>';
    endif;
  • The ‘Check first block type’ function is exactly what I need (THANK YOU!), but how do I use it outside of a loop?
    E.g., I want to show a different logo in my header if the first block isn’t a cover…
    Im getting this error:

    Notice: Trying to get property ‘post_content’ of non-object

    This is for the 404 page and archive…

    I tried adding ‘global $post;’ to the function.. I can’t get it working đŸ˜¢

  • Any way to spin this off for the last block on a page? Thanks!

  • Hey there, I would do this to get the last block.
    In addition I added a param to get the post we want by ID and a check to avoid error such as “Trying to get property ‘post_content’ of non-object”

    function friss_get_last_block_id($post=null) {
    	if(is_null($post)){
    		global $post;
    	}elseif(is_int($post)){
    		$post = get_post($post);
    	}
    
    	if($post instanceof WP_Post){     
    
    	    if(has_blocks($post->post_content)) {
    	        $blocks = parse_blocks($post->post_content);
    
    	        $last_block = end($blocks);
    	        $last_block_attrs = $last_block['attrs'];
    
    	        if(isset($last_block_attrs['id'])) {
    	            return $last_block_attrs['id'];
    	        }
    	    }
    	}
    	return false;
    }
  • Looks like this no longer works since ACF 6.0? I added the following as a workaround, but not sure how reliable this is going forward.

    
    add_filter(
        'acf/pre_save_block',
        function( $attributes ) {
            if ( empty( $attributes['id'] ) ) {
                $attributes['id'] = 'block_acf-block-' . uniqid();
            }
            return $attributes;
        }
    );
    
  • I just found out today, that the original solution no longer works, so I’m happy for dmitriy’s solution. Just remember: every page using ACF has to be saved again, for the new (old) id to be added.

    I’m really wondering why ACF made this change?

Viewing 7 posts - 1 through 7 (of 7 total)

The topic ‘Conditional to check if an instance of a block is the first on page/post’ is closed to new replies.