Home › Forums › General Issues › 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');
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.