Creating a portable Slider Block with ACF

Update 14th June 2023: As part of my demo of ACF Blocks at WordCamp Europe, this code was updated and modernised further and is available on GitHub: https://github.com/lgladdy/wceu-acf-block-demo

ACF’s upcoming 6.0 release brings support for block.json blocks, which means it’s now possible to build standalone, reusable ACF Blocks which contain all the fields, scripts, styles and templates required to display a block.

One of the significant changes to WordPress 5.9 was the introduction of an iframe wrapper for blocks inside the block editor when viewing them in various contexts, with the intent that this would apply to the core block view in an upcoming release.

This prevents styles that aren’t designed to apply to your block from being inherited, but introduces significant challenges when it comes to allowing your blocks to access JS libraries, as things like jQuery or Select2 aren’t available by default inside your block in those contexts.

You might have noticed that your block styles are no longer visible in the block pattern library or for block style previews, as these are now being displayed inside an iframe.

Because ACF 6.0 blocks support block.json (as I wrote about earlier today) you can use the block.json way of including scripts and styles, which adds support for bringing whatever libraries and styles you need for your block to work into that iframe.

To demonstrate this, I’ve built an example ACF 6.0 block which is entirely self contained as a separate plugin to demonstrate. You can drop the slider plugin in, activate it along side ACF PRO 6.0.0-alpha4 (or newer) and be good to go.

In the demo acf-block-as-a-plugin, we use block.json’s metadata to specify an array of styles that should be compiled for the block, and then a script (which currently doesn’t support being an array) that handles all the initialisation and dependencies required to include those files wherever the block is displayed. Specifically, the following lines in block.json:

    "style": [ "file:./slider.css", "file:./slick/slick.css", "file:./slick/slick-theme.css" ],
    "script": "file:./slider.js",

Those file:./ includes are system called WPDefinedAsset. It’s the system that the block editor uses for file includes in a node-like way.

The script include is a little special, as it also requires you to create a ${filename}.asset.php file in your block, which contains the metadata that would usually be passed to wp_register_script in the old world, specifically dependencies and version numbers. If you want to go all in here, in theory the @wordpress/scripts package will automatically generate this asset file you (although, I have no idea if that bit actually works yet)

Our slider.asset.php file looks like this:

<?php
return array(
	'dependencies' => array(
		'jquery',
		'slick',
	),
	'version'      => '1.0',
);

This ensures jquery and slick are also made available to us before our slider.js file is executed. (We’re using the Slick JS library to handle the slider)

As slick isn’t a built in library, we do then have to manually wp_register_script for that file before the block.json is parsed, so we do that on init inside our plugin’s core php functions, then register the block:

// We register the block on init, earlier than acf/init, so we can make sure we ask ACF to load this block's fields.
add_action( 'init', 'register_acf_block', 5 );
function register_acf_block() {
	wp_register_script( 'slick', plugin_dir_url( __FILE__ ) . 'slick/slick.js', array( 'jquery' ), '1.8.1', true );
	register_block_type( __DIR__ );
}

For field loading, we use a version of the field inclusion code I described in the earlier blog post about creating portable blocks. Specifically, we include the fields as an ACF JSON file in the block, then manually register that as part of ACF’s load routine.

// Register our block's fields into ACF.
add_action(
	'acf/include_fields',
	function() {
		$path                     = __DIR__ . '/acf-fields.json';
		$field_json               = json_decode( file_get_contents( $path ), true );
		$field_json['location']   = array(
			array(
				array(
					'param'    => 'block',
					'operator' => '==',
					'value'    => 'acf/slider',
				),
			),
		);
		$field_json['local']      = 'json';
		$field_json['local_file'] = $path;
		acf_add_local_field_group( $field_json );
	}
);

This results in a slider block that looks something like this:

An image showing the slider block.

If you want to see the full block, or even use it in your own site, you can grab the full zip for the plugin here.