Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Using Widgets and Sidebars

Amy Evans edited this page Sep 27, 2019 · 1 revision

You can register sidebars and widgets as you normally would for a WordPress site.

/**
 * Register sidebars for the site.
 */
function register_sidebars() {
	register_sidebar(
		[
			'name'          => __( 'News Sidebar', 'mysite' ),
			'id'            => 'news-sidebar',
			'description'   => __( 'News sidebar.', 'mysite' ),
			'before_widget' => '',
			'after_widget'  => '',
			'before_title'  => '',
			'after_title'   => '',
		]
	);
}
add_action( 'widgets_init',  __NAMESPACE__ . '\register_sidebars' );
/**
 * Register widgets.
 */
function register_widgets() {
	register_widget( __NAMESPACE__ . '\Header_Widget' );
}
add_action( 'widgets_init', __NAMESPACE__ . '\register_widgets' );

Create a Sidebar component and leverage the WP_Widget_Sidebar trait in WP Components. It might look something like:

class Sidebar extends \WP_Components\Component {

	use \WP_Components\WP_Post;
	use \WP_Components\WP_Widget_Sidebar;

	/**
	 * Unique component slug.
	 *
	 * @var string
	 */
	public $name = 'sidebar';

	/**
	 * Define a default config.
	 *
	 * @return array Default config.
	 */
	public function default_config(): array {
		return [
			'position' => 'right',
		];
	}

	/**
	 * Hook into post being set.
	 *
	 * @return self
	 */
	public function post_has_set(): self {
		return $this->set_sidebar( 'news-sidebar' );
	}
}

Calling set_sidebar() adds a callback, create_component_for_widget(), for widget display. During render, the callback function looks for a create_component method on your widget class, in which you would return a WP Component. For example, your widget class might look like:

<?php

class Header_Widget extends \WP_Widget {

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct(
			'header_widget',
			__( 'Header Widget', 'mysite' ),
			[
				'description' => __( 'Displays a header with text and link.', 'mysite' ),
			]
		);
	}

	/**
	 * Create a component from widget instance.
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 * @return \My_Site\Components\My_Header
	 */
	public function create_component( $args, $instance ): \My_Site\Components\My_Header {

		return ( new \My_Site\Components\My_Header() )
			->merge_config(
				[
					'header_text' => $instance['heading'] ?? __( 'Hello World', 'mysite' ),
					'header_link' => $instance['heading_link'] ?? '',
				]
			)
	}
}

Alternatively, if you do not want to use a custom create_component() method, you can define a mapping like so:

/**
 * Filter the mapping of widget classes to their callbacks.
 *
 * @param array $mapping Initial mapping.
 * @return array Modified mapping.
 */
function wp_components_widget_sidebar_mapping( $mapping ): array {
	return [
		'WP_Widget_Text' => 'create_text_component',
	];
}
add_filter( 'wp_components_widget_sidebar_mapping', __NAMESPACE__ . '\wp_components_widget_sidebar_mapping' );

That is also especially useful for Core widgets.

Finally, if you go neither of those routes, it will fallback to creating an HTML component of the content.

Clone this wiki locally