Support

Account

Home Forums General Issues ACF Pro 6 Block IDs as Attribute Not Working

Solving

ACF Pro 6 Block IDs as Attribute Not Working

  • I have an “Anchors” block that allowed the user to create hyperlinks to other Blocks on the same page. This was possible, pre-6.0, because each block had an ‘id’ attribute which I dynamically populated into a Select field. In 6.0, the ID was removed.

    I’ve followed the instructions in the ACF 6 announcement under [Block IDs](https://www.advancedcustomfields.com/resources/whats-new-with-acf-blocks-in-acf-6/#block-id). Problem is, the “anchor” attribute value is deleted from each block before the acf/pre_save_block action is completed.

    Here’s my code, per the blog post’s instructions:

    
    function mypre_add_anchor_to_blocks( $attributes ) {
    
        if( !isset($attributes['anchor']) || empty($attributes['anchor']) ) {
            $attributes['anchor'] = 'block-' . uniqid();
        }
        return $attributes;
    }
    add_filter('acf/pre_save_block', 'mypre_add_anchor_to_blocks');
    

    I’ve also tried changing the priority value of add_filter from 1-100 but it doesn’t seem to matter. I presume it’s because the function acf_get_block_type_default_attributes is overwriting the attributes, which deletes the anchor value altogether. I think this because, when I pull the anchor values from the blocks outside of a loop and long after saving, they’re visible. But whenever I update my post, the anchor value changes, implying it doesn’t exist or is empty.

    I tried finding a way to hook into the acf_get_block_type_default_attributes function but couldn’t figure it out. The closest filter I could find is $block = apply_filters( 'acf/register_block_type_args', $block ); in the file /pro/blocks.php,
    but and there doesn’t seem to be a way to add an anchor value to the attributes.

    As a (hopefully) temporary solution, I am giving all custom ACF Blocks an “Anchor ID” field which will be used to populate the Anchors’ Select field. However, this requires the client to populate those ID fields, which is an added detail they don’t particularly enjoy.

    That being said, is it possible to add anchor to a block’s default attributes? If not, is there a way to prevent the anchor attribute from being deleted before the acf/pre_save_block action? If neither of those is possible, is this a problem the ACF team could remedy, possibly by just putting a filter allowing custom attributes into the acf_get_block_type_default_attributes function?

    Thanks in advance; let me know if I’m unclear about anything I’ve written.

  • I’m not sure if you need the ID to always be the same or just unique, but if you are simply after an ID value in the template, maybe you can use something I made for a somewhat similar case. I just needed an ID for the template, without saving all the blocks again.

    I faced the same issues and the suggested solution didn’t really work as expected. Instead I used a WP filter that doesn’t get changed by ACF

    I used it to check for old align_content and align_text that are also changed in ACF 6.x, and at the same time I set the ID – if they aren’t already available.

    None of the attributes are actually saved with the block. They are dynamic and meant to be bridge old attributes that ACF removes and be available in the template.

    function acf_legacy_attributes_missing( $parsed_block, $source_block, $parent_block ) {
    
    	$parsed_block['attrs']['align_content_acf_legacy']	= ( !empty( $parsed_block['attrs']['align_content'] ) 	? $parsed_block['attrs']['align_content']	: '' );
    	$parsed_block['attrs']['align_text_acf_legacy'] 	= ( !empty( $parsed_block['attrs']['align_text'] ) 	 	? $parsed_block['attrs']['align_text'] 		: '' );
    	$parsed_block['attrs']['id'] 						= ( !empty( $parsed_block['attrs']['id'] ) 	 		 	? $parsed_block['attrs']['id'] 				: 'block_id_' . uniqid() );
        return $parsed_block;
    }
    add_filter( "render_block_data", "acf_legacy_attributes_missing", 10, 3 );
  • For some reason my reply doesn’t show. So here it is again, sorry if it shows double
    ….
    I’m not sure if you need the ID to always be the same or just unique, but if you are simply after an ID value in the template, maybe you can use something I made for a somewhat similar case. I just needed an ID for the template, without saving all the blocks again.

    I faced the same issues and the suggested solution didn’t really work as expected. Instead I used a WP filter that doesn’t get changed by ACF

    I used it to check for old align_content and align_text that are also changed in ACF 6.x, and at the same time I set the ID – if they aren’t already available.

    None of the attributes are actually saved with the block. They are dynamic and meant to be bridge old attributes that ACF removes and be available in the template.

    function acf_legacy_attributes_missing( $parsed_block, $source_block, $parent_block ) {
    
    	$parsed_block['attrs']['align_content_acf_legacy']	= ( !empty( $parsed_block['attrs']['align_content'] ) 	? $parsed_block['attrs']['align_content']	: '' );
    	$parsed_block['attrs']['align_text_acf_legacy'] 	= ( !empty( $parsed_block['attrs']['align_text'] ) 	 	? $parsed_block['attrs']['align_text'] 		: '' );
    	$parsed_block['attrs']['id'] 						= ( !empty( $parsed_block['attrs']['id'] ) 	 		 	? $parsed_block['attrs']['id'] 				: 'block_id_' . uniqid() );
        return $parsed_block;
    }
    add_filter( "render_block_data", "acf_legacy_attributes_missing", 10, 3 );
  • I need them to always be the same so that I can create a predictable hyperlink to it. The current problem is that it keeps getting regenerated every time I save the post.

  • OK – let me look into it. It should be doable by checking for an existing ID before making a new one.

  • But the question is when can you check? In my above example, I am checking during acf/pre_save_block, but at that point, the anchor attribute is already overwritten. I need to be able to hook into the function that is overwriting the attribute, but I can’t seem to find a filter that lets me do that.

  • Can the attribute name be something else than ID or Anchor? Just to avoid whatever it is ACF is doing.
    As I understand you need a unique identifier that doesn’t change on save. And it doesn’t need to be accessible for change in the editor. Right?

  • ACF removes attributes added directly to the normal attribute scope. I’m guessing it happens if it isn’t created in the field group.

    Below code adds the attribute blockId to the data scope of the block, so instead og getting from $block['blockId']you can use $block['data']['blockId']

    Hook is wp_insert_post_data

    You can probably do without the placeholder array, but I kept for debugging purposes.

    add_filter( 'wp_insert_post_data', function ( $data, $postarr ) {
    
    	// Blocks to add attribute
    	$blocks_check 	= ['acf/my-block-name','core/paragraph', 'core/heading'];
    
    	// Get saved page blocks
    	$blocks_data 	= parse_blocks( wp_unslash( $data['post_content'] ) );
    
    	// Placeholder array
    	$blocks_changed = array();
    
    	// Loop through blocks
    	foreach ( $blocks_data as $block ) {
    
    		// Check if block is in array of blocks to add attribute
    		if (!isset($block['blockName']) || !in_array($block['blockName'], $blocks_check)) {
    			$blocks_changed[] = $block;
    			continue;
    		}
    
    		// Add attributes
    		$block_changed = $block;
    		$block_changed['attrs']['data']['blockId'] = ( !empty( $block['attrs']['data']['blockId'] ) ? $block['attrs']['data']['blockId'] : 'id_' . uniqid() );
    		$blocks_changed[] = $block_changed;
    	}
    
    	//Add to error log
    	//error_log( print_r( $blocks_changed, true ) );
    
    	// Update post content
    	$data['post_content'] = serialize_blocks( $blocks_changed );
    
    	// Return data
    	return $data;
    
    }, 99, 2);
  • It just dawned on me that the whole issue might really be related to ACF filtering attributes that aren’t defined in the group and instead of going through the hoops of my function above, you could achieve the same with the ACF suggested function you already tried – just by placing the value in ['data]sub-node. Like this

    function mypre_add_anchor_to_blocks( $attributes ) {
    
    	error_log('attributes');
    	error_log( print_r( $attributes, true ) );
    
        if( !isset($attributes['data']['anchor']) || empty($attributes['data']['anchor']) ) {
            $attributes['data']['anchor'] = 'block-' . uniqid();
        }
        return $attributes;
    }
    add_filter('acf/pre_save_block', 'mypre_add_anchor_to_blocks');
Viewing 9 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic.