Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing the ACF PRO Block Versioning Developer Preview #654

Closed
lgladdy opened this issue May 12, 2022 · 415 comments
Closed

Introducing the ACF PRO Block Versioning Developer Preview #654

lgladdy opened this issue May 12, 2022 · 415 comments

Comments

@lgladdy
Copy link
Member

lgladdy commented May 12, 2022

Introducing the ACF PRO Block Versioning Developer Preview

[Update 3, 20th July 2022]
We've released a forth developer preview build with some further bug fixes, you can find the details of those further changes here.

[Update 2, 27th June 2022]
We've released a third developer preview build, you can find the details of those further changes here.

[Update 9th June 2022]
We've released a second developer preview build, you can find details of the further changes in that release here.

In the last few releases of WordPress, Gutenberg has made significant changes to all aspects of the block editor and block registration, and many of you have raised issues and feature requests to improve ACF Blocks with those improvements.

For our next release of ACF, we’re aiming to bring some key new features to ACF Blocks to take advantage of those new features from Gutenberg, as well as improving existing blocks. We’re releasing a preview build today, early in our development cycle, so we can get your feedback and bug reports early in development.

You can download this preview (tagged as 6.0.0-alpha1) from your account now. This build is ACF PRO 5.12.2 with the following changes:

Block.json support

Since WordPress 5.8, WordPress has supported - and recommended - that blocks are registered through a JSON configuration file. All of the WordPress Block Documentation was migrated to only show block.json configuration objects, and it became confusing for users to know what WordPress configuration options were usable in ACF PRO. This build introduces support for block.json registration of blocks with ACF.

For blocks registered through a block.json file, you can mark them as ACF Blocks by adding a new ACF configuration key to the JSON file, which contains the ACF specific configuration, for example:

{
    "name": "all-fields-block",
    "title": "All Fields Test Block",
    "description": "All fields test block",
    "style": "file:./all-fields-block.css",
    "category": "theme",
    "icon": "admin-comments",
    "apiVersion": 2,
    "keywords": [
        "test",
        "quote"
    ],
    "acf": {
        "mode": "preview",
        "renderTemplate": "all-fields-block.php"
    },
    "styles": [
        { "name": "default", "label": "Default", "isDefault": true },
        { "name": "red", "label": "Red" },
        { "name": "green", "label": "Green" },
        { "name": "blue", "label": "Blue" }
    ],
    "supports": {
        "align": true,
        "anchor": true,
        "alignContent": false,
        "color": {
            "text": true,
            "background": true,
            "link": true
        },
        "alignText": true,
        "spacing": {
            "margin": [
                "top",
                "bottom"
            ],
            "padding": true
        },
        "typography": {
            "lineHeight": true,
            "fontSize": true
        },
        "fullHeight": true
    },
    "attributes": {
        "backgroundColor": {
            "type": "string",
            "default": "purple"
        }
    },
    "example": {
        "attributes": {
            "data": {
                "text": "This is an example text field",
                "text_area": "This is an example text area field"
            }
        }
    }
}

You then need to use the standard WordPress block registration function register_block_type, rather than acf_register_block_type:

register_block_type( 'path/to/folder/containing/block.json' );

If you don't specify a namespace for your block like in our example above: "name": "all-fields-block",, ACF will automatically add it if it is an ACF block to become the equivalent of "name": "acf/all-fields-block",

Upon release, this new method of registering blocks will become the recommended way to register a block, replacing the acf_register_block_type function.

The renderTemplate property should either be a full path to the template file, or relative to the location of the JSON file.

WordPress uses a camelCase format inside JSON files, and ACF adopts that too. Configuration keys such as render_template when used in acf_register_block_type need to be renderTemplate when used in JSON, likewise align_content and full_height should be alignContent and fullHeight for example. All previous configuration objects are supported, except for enqueue_style, enqueue_script and enqueue_assets for the following reason:

Asset Loading

When ACF Blocks was first introduced, it supported enqueueing block specific assets before WordPress had native support. Recent (and upcoming) updates to Gutenberg will require these assets to be loaded using specific WordPress asset configuration keys such as editorScript, script, editorStyle and style.

WordPress 5.9 users who use Block Styles may have noticed that the ACF registration of styles was not applied to those previews, which is why all ACF Block users should migrate their blocks to use those WordPress provided methods of asset loading.

The previous methods of asset loading in ACF Blocks will continue to work for the time being in acf_register_block_type, but as WordPress continues to make changes across releases we expect that to stop working.

Block ID removal

This release of ACF will remove saved block IDs from ACF Blocks. This means you can easily copy and paste blocks, simplify your post type templates or block patterns, or duplicate blocks without having any issues where block IDs clash.

We’re hoping this change is transparent to users, and any existing blocks will have their block IDs removed the first time they’re edited after installing this build. We’ll still generate a $block['id'] for your templates as we know some users use that for element IDs, but the format of those IDs will change, and may be duplicated if you have multiple blocks on the same page with the exact same data (similar to how block IDs are the same inside a query loop block now)

Because of this, if you want to downgrade to ACF 5.12 after installing this build, you may experience warnings in your templates until you edit a block if you are relying on $block['id'] in a template without checking if it exists.

Block Versioning

One of the issues we’ve had with ACF Blocks development is that we haven’t been able to react to new Gutenberg features as fast as we’d like due to the requirement to maintain backwards compatibility with blocks created potentially as far back as WordPress 5.3.

This release of ACF brings block versioning, meaning we can make backwards compatibility breaking changes whenever necessary, allowing users to opt in to them to enable new features.

A new blockVersion (inside the ACF key in block.json) or acf_block_version (if using acf_register_block_type) key is now supported. For blocks registered via block.json, this defaults to 2, and for acf_register_block_type, this defaults to 1.

For now, the only change between the two versions is the way <InnerBlocks /> markup is rendered. If you use block version 2 (which requires WordPress 5.8+), the container markup when using InnerBlocks will match between backend and frontend rendering, with any inner blocks wrapped in a new (and single level) <div class="acf-inner-blocks-container"></div> element. This can help make your CSS layouts easier, as you can be sure both render views have the same markup.

Block Registry Standardization

In previous versions of ACF PRO, a lightweight shim of the block configuration was registered in PHP, and then the full configuration registered in JS.

In this build of ACF the full block configuration is now saved in the WordPress PHP Block Registry. This makes it easier for you to access details of the block configuration in your templates or render callback should you wish.

Block Bug Fixes

We’ve fixed a few reported bugs with ACF Blocks in this build as well. For example, content after <InnerBlocks /> will now render correctly without the need to wrap it in another div, and alignText will now always default to the WordPress default of left rather than an empty string.

Wrap up

We hope you’ll take the time to test this build of ACF - we’re particularly interested in feedback on how your upgrades go to make sure there are no issues with the block ID removal system.

Please leave any comments, bugs or feedback here on this GitHub issue. We’ve left a few debug console messages in this build to try and help us detect any issues with block preloading or rendering, so screenshots of your browser console will likely be especially useful with any bug reports!

@JiveDig
Copy link

JiveDig commented May 12, 2022

This is great news, thanks for the hard work thus far! I have a few quick questions that will likely help others test as well.

  1. Can we see an example of loading/enqueuing assets the new way?
  2. Is this new way only relevant when registering blocks via JSON?

I can't wait to test out the v2 markup changes :)

@lgladdy
Copy link
Member Author

lgladdy commented May 12, 2022

@JiveDig

  1. Sure! You can see an example in the block.json above on how to include assets, and more details on the WordPress docs (as you can pass in a script/style handle if you've already registered it).

Specifically:

"style": "file:./all-fields-block.css",

That's loading a file called "all-fields-block.css" in the same folder as the block.json whenever the block is added to a page.

  1. That's actually a good question - and I took a quick look at the WordPress core code for register_block_type_from_metadata which is the function it uses internally, and it looks like the functions for that are exclusive to that function which isn't executed for the old way. So I think the answer is no. Edit: Turns out, this will work - but you need to pass a script or style handle that has previously been registered outside of the block.

I'll look into this a bit deeper to see if we can manually add support for it, but that might not be possible for other reasons that is specific to the block.json loading.

@JiveDig
Copy link

JiveDig commented May 12, 2022

Okay great, thanks.

  1. Duh! I looked too quickly and was looking for the word register, enqueue, or asset, not "style" or "script".
  2. We have some complex blocks with field groups registered in PHP. I'm not super clear on how to convert them to JSON and still register the fields in PHP for those blocks, but I'll dive in a bit ASAP.

@lgladdy
Copy link
Member Author

lgladdy commented May 12, 2022

@JiveDig Yeh - we definitely will get migration guides and such in the release documentation. Let me know if you need any help though. For my own dev test blocks I actually just copy/pasted the PHP array and converted it to JSON format, but you could always do:

echo json_encode($block_configuration_array, JSON_PRETTY_PRINT);
die();

to get the start point out from the PHP code for the old way!

@JiveDig
Copy link

JiveDig commented May 12, 2022

I got ya. I was thinking acf_add_local_field_group() was also moving to JSON somehow. Registering the actual block in JSON will be an easy conversion. Registering field groups in JSON would definitely not be fun :)

@CreativeDive
Copy link
Collaborator

CreativeDive commented May 13, 2022

@lgladdy oh wow, a lot of changes. I will need some time to test all of this changes. But here is my first feedback. I have created this issue #655

It seems this is already fixed by the new alpha version. The field values are now present :-)

@CreativeDive
Copy link
Collaborator

@lgladdy it seems there is something broken with the default alignText change to left.

I have registered a block like this:

acf_register_block_type(
	array(
		'name' => 'button',
		'title' => __('Buttons', 'wphave'),
		...
		'align_text' => 'left', // --> Optional default value
		'supports' => array(
			'align_text' => true, // --> Enable the text alignment control
			...
		),
		...
	)
);

In a specific post I have used this block and the align_text was set to center.

Before the new alpha version, everything looks good with the alignment. After using the new alpha now this align_text is set to left. But before it was saved to center.

It seems there is something wrong and should be improved.

@CreativeDive
Copy link
Collaborator

@lgladdy For now, the change from removing block IDs looks good. The block IDs no longer exist.

I have copied some ACF blocks and made changes to each copied block and it seems there are no longer issues with the field values was set to a wrong block.

But this issue #605 is still there:

May-13-2022.08-58-41.mp4

It only works properly after the post has been saved and reloaded. But not if the block was only inserted after copying. Then correct field changes are not present.

Is there any hope to get this fixed?

@CreativeDive
Copy link
Collaborator

@lgladdy this issue #650 is fixed by using the new alpha. Thank you.

@CreativeDive
Copy link
Collaborator

CreativeDive commented May 13, 2022

@lgladdy the $block var still contains the "id" attribute:

error_log(print_r($block,true));

...
[id] => block_b11dfd57e4d7a1b736e8632b9b0fcbca
...

This id is no longer used for allocating ACF blocks. Thank you! But will this attribute remain in the $block var in the future?

@lgladdy
Copy link
Member Author

lgladdy commented May 13, 2022

@lgladdy the $block var still contains the "id" attribute:

error_log(print_r($block,true));

...
[id] => block_b11dfd57e4d7a1b736e8632b9b0fcbca
...

This id is no longer used for allocating ACF blocks. Thank you! But will this attribute remain in the $block var in the future?

Yup - the block ID is just a hash of the attributes, but we need to keep $block['id'] there for backwards compatibility reasons with users templates. We don't want to start firing warnings because they're using it for element IDs!

@lgladdy
Copy link
Member Author

lgladdy commented May 13, 2022

@lgladdy it seems there is something broken with the default alignText change to left.

I have registered a block like this:

acf_register_block_type(
	array(
		'name' => 'button',
		'title' => __('Buttons', 'wphave'),
		...
		'align_text' => 'left', // --> Optional default value
		'supports' => array(
			'align_text' => true, // --> Enable the text alignment control
			...
		),
		...
	)
);

In a specific post I have used this block and the align_text was set to center.

Before the new alpha version, everything looks good with the alignment. After using the new alpha now this align_text is set to left. But before it was saved to center.

It seems there is something wrong and should be improved.

Thanks, I'll look into this one. This is probably because we also turned "align_text" into "alignText"; our upgrade code probably picked up the default value over the set value and didn't change it.

@CreativeDive
Copy link
Collaborator

@lgladdy The "Block Versioning" is a very good idea to handle the issue with the block markup. Thank you!

I can confirm the markup for inner blocks is now more simple than before:

Block version 1:

<div class="block-editor-inner-blocks">
<div class="block-editor-block-list__layout" data-is-drop-zone="true">
... innerBlocks ...
</div>
</div>

Block version 2:

<div class="acf-inner-blocks-container block-editor-block-list__layout" data-is-drop-zone="true">
... innerBlocks ...
</div>

This looks good and is the first way in the right direction. Thank you.

But we can't wait for the complete change to make the ACF block markup more simple also for the ACF block itself. :-)

Here is another question to the markup. It seems there is no way to remove the <div class="acf-inner-blocks-container container completely, right?

I asking because, CSS selectors like ".my-acf-block > .my-inner-item" dosen't work if there is the <div class="acf-inner-blocks-container between this elements.

BUT, only ONE additional ACF container is better than a lot of additional ACF containers.

With only one additional ACF container it's more easier to the handle this thing by ".my-acf-block > .acf-inner-blocks-container > .my-inner-item".

@lgladdy
Copy link
Member Author

lgladdy commented May 13, 2022

@lgladdy For now, the change from removing block IDs looks good. The block IDs no longer exist.

I have copied some ACF blocks and made changes to each copied block and it seems there are no longer issues with the field values was set to a wrong block.

But this issue #605 is still there:

May-13-2022.08-58-41.mp4

It only works properly after the post has been saved and reloaded. But not if the block was only inserted after copying. Then correct field changes are not present.

Is there any hope to get this fixed?

Could you remake this video with console open too? For this test, we're logging all the internal IDs (which WordPress handles now) along with all the requests that take place to the renderer, so we should be able to figure out what's happening; but this does point to it being a Gutenberg bug now WordPress is responsible for handling block IDs.

@lgladdy
Copy link
Member Author

lgladdy commented May 13, 2022

@lgladdy The "Block Versioning" is a very good idea to handle the issue with the block markup. Thank you!

I can confirm the markup for inner blocks is now more simple than before:

Block version 1:

<div class="block-editor-inner-blocks">
<div class="block-editor-block-list__layout" data-is-drop-zone="true">
... innerBlocks ...
</div>
</div>

Block version 2:

<div class="acf-inner-blocks-container block-editor-block-list__layout" data-is-drop-zone="true">
... innerBlocks ...
</div>

This looks good and is the first way in the right direction. Thank you.

But we can't wait for the complete change to make the ACF block markup more simple also for the ACF block itself. :-)

Here is another question to the markup. It seems there is no way to remove the <div class="acf-inner-blocks-container container completely, right?

I asking because, CSS selectors like ".my-acf-block > .my-inner-item" dosen't work if there is the <div class="acf-inner-blocks-container between this elements.

BUT, only ONE additional ACF container is better than a lot of additional ACF containers.

With only one additional ACF container it's more easier to the handle this thing by ".my-acf-block > .acf-inner-blocks-container > .my-inner-item".

Honestly, I don't think we'll get any simpler than we have now, until WordPress introduce new features (like they did which let us fix the <InnerBlocks /> markup, which was useInnerBlockProps. WordPress needs all those wrappers around the main block in order to support all the toolbars and things for now - and I suspect there is little value for them to do that as for the overwhelming majority of cases, the current setup is fine.

As for removing the container, nope - that's not possible for the same reasons. Gutenberg (via React) uses the container to know where things can be dragged/dropped etc, and where the "Add New" buttons should appear etc.

@CreativeDive
Copy link
Collaborator

@lgladdy I like the new way to register ACF block in the Block.json way. I will test this soon.

@CreativeDive
Copy link
Collaborator

Honestly, I don't think we'll get any simpler than we have now, until WordPress introduce new features (like they did which let us fix the markup, which was useInnerBlockProps. WordPress needs all those wrappers around the main block in order to support all the toolbars and things for now - and I suspect there is little value for them to do that as for the overwhelming majority of cases, the current setup is fine.

As for removing the container, nope - that's not possible for the same reasons. Gutenberg (via React) uses the container to know where things can be dragged/dropped etc, and where the "Add New" buttons should appear etc.

@lgladdy Yes, that's what I thought. I think we can deal with that. Because now, in this case, it's just a container.

What is still missing is the markup simplification for the ACF block itself.

@CreativeDive
Copy link
Collaborator

CreativeDive commented May 13, 2022

Could you remake this video with console open too? For this test, we're logging all the internal IDs (which WordPress handles now) along with all the requests that take place to the renderer, so we should be able to figure out what's happening; but this does point to it being a Gutenberg bug now WordPress is responsible for handling block IDs.

May-13-2022.09-57-22.mp4

@lgladdy Here is the full log of the console:

Bildschirmfoto 2022-05-13 um 09 54 32

Bildschirmfoto 2022-05-13 um 09 54 48

Bildschirmfoto 2022-05-13 um 09 55 20

I hope this is helping you.

@CreativeDive
Copy link
Collaborator

Thanks, I'll look into this one. This is probably because we also turned "align_text" into "alignText"; our upgrade code probably picked up the default value over the set value and didn't change it.

@lgladdy ok, this means we have to change nothing here right?

@CreativeDive
Copy link
Collaborator

@lgladdy Currently I'm trying to test the new feature to load ACF blocks via the block.json file, but I'm having trouble with the script assets:

Using "style": "file:./acf-block-style.css" is working fine.

Using "script": "file:./acf-block.js" is not working.

I get the following message.

register_block_script_handle was called incorrectly. The asset file for the "script" defined in "acf/documentation-menu" block definition is missing. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.)

This JS file exists and the path is correct. What is wrong here?

@CreativeDive
Copy link
Collaborator

CreativeDive commented May 16, 2022

@lgladdy I want to ask you if acf_register_block_type() will supported in the future? You wrote:

The previous methods of asset loading in ACF Blocks will continue to work for the time being in acf_register_block_type, but as WordPress continues to make changes across releases we expect that to stop working.

I have worked out that both methods should be supported:

  1. For a large amount of blocks it's very easy to manage blocks via acf_register_block_type() in one file.
    --> For a large amount (like 80+) of blocks using block.json you have to 80+ files to manage. A lot.

  2. Using acf_register_block_type() allows me to use PHP variables. E.g. for block icons, I use a function like get_svg_icon('arrow'), to load custom icons to my ACF blocks.
    --> This is more difficult by using block.json

  3. I have custom post types, which represents some parts of section of the website. I my case I don't use the default FSE of WordPress. I have an own way to provide FSE with own post types. Also loading assets I use an own way.
    --> I'm not sure if the WordPress default assets loading is supporting blocks that comes not from the default "the_content". Maybe the asset loading system of WordPress is not working in cases like this.

  4. Adding blocks in PHP via acf_register_block_type() is more user friendly than using block.json.

  5. It seems loading multiple script assets using block.json is not possible, do you have an hint for me how we can load multiple styles and scripts using block.json?

"script": "file:assets/js/script_1.js",
"script": "file:assets/js/script_2.js"
  1. A other thing is the translation of text strings. I use "Poedit" to create language files. At the moment I think it's not possible to find text string inside a block.json file for "Poedit" to translate this strings. This is one more thing why using block.json is more difficult.

In other words, acf_register_block_type() should be supported in the future, because using this way can have advantages.

@CreativeDive
Copy link
Collaborator

@lgladdy I was wondering if a solution would make sense for ACF to automatically create a block.json file for each block using acf_register_block_type()?

@lgladdy
Copy link
Member Author

lgladdy commented May 16, 2022

@lgladdy I want to ask you if acf_register_block_type() will supported in the future? You wrote:

The previous methods of asset loading in ACF Blocks will continue to work for the time being in acf_register_block_type, but as WordPress continues to make changes across releases we expect that to stop working.

I have worked out that both methods should be supported:

  1. For a large amount of blocks it's very easy to manage blocks via acf_register_block_type() in one file.
    --> For a large amount (like 80+) of blocks using block.json you have to 80+ files to manage. A lot.
  2. Using acf_register_block_type() allows me to use PHP variables. E.g. for block icons, I use a function like get_svg_icon('arrow'), to load custom icons to my ACF blocks.
    --> This is more difficult by using block.json
  3. I have custom post types, which represents some parts of section of the website. I my case I don't use the default FSE of WordPress. I have an own way to provide FSE with own post types. Also loading assets I use an own way.
    --> I'm not sure if the WordPress default assets loading is supporting blocks that comes not from the default "the_content". Maybe the asset loading system of WordPress is not working in cases like this.

You'd likely need to look into the WordPress source here to see what filters/action it fires at each point you're looking to do something custom. We've found that there does tend to be filters and actions at most sensible points, so it should be possible!

  1. Adding blocks in PHP via acf_register_block_type() is more user friendly than using block.json.
  2. It seems loading multiple script assets using block.json is not possible, do you have an hint for me how we can load multiple styles and scripts using block.json?
"script": "file:assets/js/script_1.js",
"script": "file:assets/js/script_2.js"

This is dependant on WordPress's support for it, you can see that by each line of their documentation at https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/ or the block schema. Currently script does not support being an array, so you'd need to concat your scripts together. Other enqueues do support it, from various versions of WordPress.

In other words, acf_register_block_type() should be supported in the future, because using this way can have advantages.

We'll support it as long as WordPress does - which should be for the foreseeable future, but you're likely going to notice things like asset enqueuing breaking before that support goes, as the WordPress enqueue system for blocks doesn't work unless you use block.json. We'll investigate if we can backport it into acf_register_block_type, but that might not be possible.

You may also miss out of new features that WordPress brings, as it's starting to put code exclusively in the block.json parsing functions.

Remember, this change is dictated by WordPress rather than us. There are filters you can use to modify block.json too if you wanted to use PHP functions to set things like svg icons.

@lgladdy
Copy link
Member Author

lgladdy commented May 16, 2022

@lgladdy Currently I'm trying to test the new feature to load ACF blocks via the block.json file, but I'm having trouble with the script assets:

Using "style": "file:./acf-block-style.css" is working fine.

Using "script": "file:./acf-block.js" is not working.

I get the following message.

register_block_script_handle was called incorrectly. The asset file for the "script" defined in "acf/documentation-menu" block definition is missing. Please see Debugging in WordPress for more information. (This message was added in version 5.5.0.)

This JS file exists and the path is correct. What is wrong here?

I'll take a look at this - that looks sensible to me, unless there's another acf-block.js on the include path, or something is modifying the include paths.

@CreativeDive
Copy link
Collaborator

CreativeDive commented May 16, 2022

@lgladdy

I'll take a look at this - that looks sensible to me, unless there's another acf-block.js on the include path, or something is modifying the include paths.

There exists no other script like this. I have tried to load the script directly in the block directory or to load in a sub folder of the block directly. Each time I will get this notice.

By investigating this:

$filter_metadata_registration = function( $settings, $metadata ) {
	error_log(print_r($settings,true));
	return $settings;
};
add_filter( 'block_type_metadata_settings', $filter_metadata_registration, 10, 2 );
		
register_block_type_from_metadata( __DIR__ );

I can see the 'script' attribute is empty.

@lgladdy
Copy link
Member Author

lgladdy commented Sep 1, 2022

@lgladdy Yes, of course I can understand that very well. I'm wondering if you load a block script that includes the dependency on ACF scripts, can it possibly load the necessary ACF scripts?

I suspect the performance of re-initing everything for a block might be too much - especially as we'd need to load things like select2 and date/time pickers etc. Essentially the full ACF stack including third party libraries.

My hope is the back compat mode they're working on won't have any downsides to us opting into for all ACF blocks - as it will run those blocks like it does now.

@CreativeDive
Copy link
Collaborator

@lgladdy I just tested it. It may be possible to specify an ACF dependency and ACF scripts will then load in tablet/mobile preview.

Yes, there are probably many scripts that ACF needs to load. But theoretically that could be a workaround if there is no other option in the future. But I suspect that there will be a possibility through Wordpress.

@CreativeDive
Copy link
Collaborator

@lgladdy I have a question. Is there a way inside an inner block to find out which block type is the parent?

So far I only know the way to query an ACF field of the parent block via "providesContext", whether it exists or not. But I don't like this solution.

@lgladdy
Copy link
Member Author

lgladdy commented Sep 8, 2022

@CreativeDive I actually don't know if you could set a fixed string to pass through to providesContext? I'll take a look once we've shipped 6.0 and get back to you!

@lgladdy
Copy link
Member Author

lgladdy commented Sep 8, 2022

@CreativeDive Actually, wait... we store name as an attribute. Could you use "providesContext": {"acf/blockname": "name"}, and then "usesContext": ["acf/blockname"], in the child?

@CreativeDive
Copy link
Collaborator

@lgladdy Thanks very much! A nice way! That's exactly what I needed and it works. A helpful note for the ACF block documentation.

@CreativeDive
Copy link
Collaborator

@lgladdy I have an additional question. Should "providesContext": {"acf/blockname": "name"} be used as carefully as "providesContext": {"acf/fields": "data"} for performance reasons?

@JiveDig
Copy link

JiveDig commented Sep 12, 2022

Struggling with "usesContext": [ "acf/fields" ], in my nested parent/child ACF blocks. I can successfully consume the parent block settings via the child block, but it's raw repeater field data. See below:

image

  1. Is there a way to get the repeater data formatted how get_field() would return it?
  2. Is it possible to format the field (and any other) data manually and pass it to the child block(s)?

@CreativeDive
Copy link
Collaborator

@JiveDig I solved it like this:

$field = my_acf_parent_block_field( 'field_name', $context );

if ( ! function_exists( 'my_acf_parent_block_field' ) ) :

	function my_acf_parent_block_field( $field_name, $context ) {

		// Get the parent block ACF fields from $context if provided
		$context = isset( $context['acf/fields'] ) ? $context['acf/fields'] : array();

		// Get the correct field, depending on the "field_name" or "field_key" is passed
		$context_data = acf_setup_meta( $context );
		
		// Get the field value
		$value = isset( $context_data[$field_name] ) ? $context_data[$field_name] : '';

		// Get the field object
		$field = get_field_object( $field_name );
		
		// Get the formatted value if exists
		$value = apply_filters( 'acf/format_value', $value, '', $field );
		
		return $value;

	}

endif;

@JiveDig
Copy link

JiveDig commented Sep 12, 2022

@CreativeDive That looks nice. Have you tested that when field_name is the parent repeater field name? Or do you still need to use this for each sub_field name?

I'd still love to be able to add my own data to $context before it gets passed to the child blocks. That would be a great addition IMO.

@CreativeDive
Copy link
Collaborator

@JiveDig No, I haven't tried it for repeater data. acf_setup_meta( $context ) does the magic here.

I think getting this to work with repeater data isn't the problem. But I can't say more about it because I use it in a small area of field data.

@JiveDig
Copy link

JiveDig commented Sep 12, 2022

Definitely looks like repeater data isn't working as expected here.

@JiveDig
Copy link

JiveDig commented Sep 13, 2022

@lgladdy (or anyone), is there a list of the things that can be passed to the child blocks via usesContext? I'm wondering if we can pass the parent block ID/reference so we can use it in get_field( 'my_key', $block_id ) to get the repeater values from the parent block. Still trying to work through a way to get all of the parent block setting values via the child block.

@lgladdy
Copy link
Member Author

lgladdy commented Sep 14, 2022

@JiveDig You can pass any data assigned to the block comment through with usesContext - so if you look in code view, any of the JSON keys you see there.

This is all raw client side data though, which is why ACF can't do anything magical here to help you parse the data. acf_setup_meta will help here - but like you've suggested, for some reason (I haven't had time to investigate why yet!), it will not handle repeaters properly in the returned output.

To get around this, I suspect you could pass a second parameter to acf_setup_meta($context, 'block_context_<someid>'), and then use get_field('repeater', 'block_context_<someid>'); to get the processed data.

You can use just block_context if you like, without an ID, given it probably won't matter if the next block overwrites that data?

In the future, I'd expect we'll get some kind of acf_build_context_data() function into core for you, but given this context was just a quick thing I managed to get into the 6.0 release as an MVP, we'll work more on this over our next few releases.

@JiveDig
Copy link

JiveDig commented Sep 14, 2022

@lgladdy This seems much more promising than manually getting the rows, but it seems to only return the first row.

This works, but is messy:

// $context is the acf/fields data.

// Key => Default.
$repeaters    = [
	'arrangement'    => '1/4',
	'arrangement_md' => '1/3',
	'arrangement_sm' => '1/2',
	'arrangement_xs' => '1/1',
];

$args = [];

foreach ( $repeaters as $name => $default ) {
	$args[ $name ] = [];

	$value = isset( $context[ $name ] ) ? $context[ $name ] : null;

	if ( is_null( $value ) ) {
		$args[ $name ][] = $default;
		continue;
	}

	// Array starts with 0 but rows count starts with 1.
	for ( $i = 0; $i < (int) $value; $i++ ) {
		$sub_key         = sprintf( '%s_%s_columns', $name, $i );
		$sub_value       = isset( $context[ $sub_key ] ) ? $context[ $sub_key ] : [ $default ];
		$args[ $name ][] = $sub_value;
	}
}

This is cleaner but only gets the first row, or at least I think that's what's happening.

// $context is the acf/fields data.
$setup = acf_setup_meta( $context, 'block_context' );

// Key => Default.
$repeaters    = [
	'arrangement'    => '1/4',
	'arrangement_md' => '1/3',
	'arrangement_sm' => '1/2',
	'arrangement_xs' => '1/1',
];

$args = [];

foreach ( $repeaters as $name => $default ) {
	$args[ $name ] = [];
	$values        = get_field( $name, 'block_context' );

	if ( ! $values ) {
		$args[ $name ][] = $default;
		continue;
	}

	foreach ( (array) $values as $value ) {
		$args[ $name ][] = isset( $value['columns'] ) ? $value['columns'] : $default;
	}
}

@JiveDig
Copy link

JiveDig commented Sep 19, 2022

I'm hitting a new, and concerning issue. I have parent/child blocks, both built with ACF. Each child ACF block will often have identical settings, but the markup needs to be different, based on the parent block settings as well as the current index/item.

I'm finding out that if the child blocks have identical settings it seems they are cached/hashed and rendered without parsing again, which breaks my output.

If I dump/debug in my callback for each child block, only the first one triggers anything at all.

Is there a way to force everything from parsing, even if the child block settings are the same?

@JiveDig
Copy link

JiveDig commented Sep 19, 2022

It also seems that I need to save a block change, then refresh the editor, for it to re-parse the block and display correctly. Maybe I'm just not understanding how ACF is handling each child block and I can handle things in my code to make it work, or maybe it's a bug or FR for ACF?

@lgladdy

@JiveDig
Copy link

JiveDig commented Sep 19, 2022

Okay weird. this parent/child thing seems to only happen in the editor.

@CreativeDive
Copy link
Collaborator

@JiveDig I think this issue is related to how ACF is caching blocks. If a block is identical, the same hash is used? @lgladdy seems very busy right now.

@JiveDig
Copy link

JiveDig commented Sep 19, 2022

Yeah this is a tricky one. Since we can pass parent block settings to the child, there are definitely times where the parent settings will determine what happens in the child, so hashing like this will have issues. I love the performance benefits, but I'm hoping there is a fix, otherwise I'm back to the drawing board.

@CreativeDive
Copy link
Collaborator

@JiveDig I've been working on my WordPress theme for years now. The last few years have been very frustrating due to the many changes to WordPress. It somehow never ends. I'm glad that many pain points in ACF have been fixed. Still, the new "I can customize everything" thing seems to be a very tedious thing to do if you want to properly expand FSE. I'm still encountering issues I can't understand why WordPress didn't think things through properly. I can understand that very well. There is a lot of time in our work.

@JiveDig
Copy link

JiveDig commented Sep 19, 2022

@CreativeDive Sidenote, but related, are you in any WP Slack groups or somewhere we can chat? I pinged you on Twitter earlier. We're very aligned in our approach to things so it would be cool to keep in touch outside of ACF issues :D

@CreativeDive
Copy link
Collaborator

@JiveDig I've never used Slack, but can you send me a link to join? You can write me at [email protected]

@polevaultweb
Copy link
Contributor

polevaultweb commented Sep 19, 2022

@lgladdy seems very busy right now.

@CreativeDive It's been a public holiday in the UK today and Liam and Matt are both working extremely hard on the 6.0 release due very soon. I'm sure Liam will take a look when he can.

@polevaultweb
Copy link
Contributor

It might be a good idea to try and keep new conversations off this issue so they don't get lost on the ever expanding thread. Feel free to open new individual issues.

@CreativeDive
Copy link
Collaborator

Liam and Matt are both working extremely hard on the 6.0 release due very soon

@polevaultweb sure, we know :-)

Thanks for the information !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests