Block-based Widget Areas

The next phase of Gutenberg includes bringing the block editor to the Widgets screen. But we’re building websites that need this functionality right now.

I’ve come up with a simple solution for using the block editor outside of the main content area, in contexts where we used to use widget areas.

Register a Block Area post type

I create a custom post type called “Block Area”, and each unique block area is a post. To display the block area, we query for the block_area post with a specific slug and display its contents.

I built it as a class that I include in our core functionality plugin. To display the after-post block area, I add this to my theme’s single.php file:

if( function_exists( 'ea_block_area' ) )
	ea_block_area()->show( 'after-post' );

Once WordPress core adds block-based widget areas, I can migrate the block content from my block_area post type to whatever WordPress core uses, and update the show() method to use dynamic_sidebar() or a new function in WP core.

Example

I’m working on a website with an “After Post” block area for blocks that appear at the end of every article.

Code for Block Areas

I recommend including this in a core functionality plugin. You can then use the ea_block_area() function in your theme after checking if the function exists.

<?php
/**
 * Block Area
 * CPT for block-based widget areas, until WP core adds block support to widget areas
 * @link https://www.billerickson.net/wordpress-gutenberg-block-widget-areas/
 *
 * @package      CoreFunctionality
 * @author       Bill Erickson
 * @since        1.0.0
 * @license      GPL-2.0+
**/

class EA_Block_Area {

	/**
	 * Instance of the class.
	 * @var object
	 */
	private static $instance;

	/**
	 * Class Instance.
	 * @return EA_Block_Area
	 */
	public static function instance() {
		if ( ! isset( self::$instance ) && ! ( self::$instance instanceof EA_Block_Area ) ) {
			self::$instance = new EA_Block_Area();

			// Actions
			add_action( 'init',              array( self::$instance, 'register_cpt'      )    );
			add_action( 'template_redirect', array( self::$instance, 'redirect_single'   )    );
		}
		return self::$instance;
	}

	/**
	 * Register the custom post type
	 *
	 */
	function register_cpt() {

		$labels = array(
			'name'               => 'Block Areas',
			'singular_name'      => 'Block Area',
			'add_new'            => 'Add New',
			'add_new_item'       => 'Add New Block Area',
			'edit_item'          => 'Edit Block Area',
			'new_item'           => 'New Block Area',
			'view_item'          => 'View Block Area',
			'search_items'       => 'Search Block Areas',
			'not_found'          => 'No Block Areas found',
			'not_found_in_trash' => 'No Block Areas found in Trash',
			'parent_item_colon'  => 'Parent Block Area:',
			'menu_name'          => 'Block Areas',
		);

		$args = array(
			'labels'              => $labels,
			'hierarchical'        => false,
			'supports'            => array( 'title', 'editor', 'revisions' ),
			'public'              => false,
			'show_ui'             => true,
			'show_in_rest'	      => true,
			'exclude_from_search' => true,
			'has_archive'         => false,
			'query_var'           => true,
			'can_export'          => true,
			'rewrite'             => array( 'slug' => 'block-area', 'with_front' => false ),
			'menu_icon'           => 'dashicons-welcome-widgets-menus',
		);

		register_post_type( 'block_area', $args );

	}

	/**
	 * Redirect single block areas
	 *
	 */
	function redirect_single() {
		if( is_singular( 'block_area' ) ) {
			wp_redirect( home_url() );
			exit;
		}
	}

	/**
	 * Show block area
	 *
	 */
	function show( $location = '' ) {
		if( ! $location )
			return;

		$location = sanitize_key( $location );

		$loop = new WP_Query( array(
			'post_type'		=> 'block_area',
			'name'    		=> $location,
			'posts_per_page'	=> 1,
		));

		if( $loop->have_posts() ): while( $loop->have_posts() ): $loop->the_post();
			echo '<div class="block-area block-area-' . $location . '">';
				the_content();
			echo '</div>';
		endwhile; endif; wp_reset_postdata();
	}

}

/**
 * The function provides access to the class methods.
 *
 * Use this function like you would a global variable, except without needing
 * to declare the global.
 *
 * @return object
 */
function ea_block_area() {
	return EA_Block_Area::instance();
}
ea_block_area();

Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments

    • Bill Erickson says

      Very cool! I haven’t seen that before. That seems to be a great way to get blocks into existing widget areas.

Leave A Reply