Skip to content

Creating a custom widget

Radoslav Georgiev edited this page Oct 21, 2018 · 3 revisions

Creating a custom widget

Overview

The Widget location only works with existing widgets, but if you want to create a new widget and use the location to add fields to it, it is still fairly easy to do so. In this tutorial we will create a new Accordion widget, which will display a few text areas and allow users to switch between them.

The widget has already been implemented as the accordion-widget module of the Showcase theme.

Widgets API and Ultimate_Fields\Custom_Widget

The Widgets API article at the Codex explains that to create a new widget, you need to extend the WP_Widget class, as well as the methods that you need to implement when extending it. As you will be using Ultimate Fields for the fields and values in the widget, you should not need to implement the form and update methods of the class.

Ultimate Fields provides you with the additional Ultimate_Fields\Custom_Widget class. The class extends WP_Widget and adds the needed functionality for displaying the form of the widget and updating it, leaving you concerned only with the fields and display of the widget.

Preparation

Using the right action

If you are creating a new widget, which relies completely on Ultimate Fields for its fields, you need to make sure that Ultimate Fields is present before registering the widget.

Since Ultimate FIelds is a plugin, it is possible that it is not installed or active at some point. Therefore, you should use the uf.init action, which is triggered by Ultimate Fields. This way the widget will not be available until the plugin is installed and activated.

On that action you should extend the base widget class for your widget, in this case Showcase_Accordion_Widget. For this example, the actual widget class is isolated in a separate file, called Showcase_Accordion_Widget.php.

Registering the widget

In order to let WordPress know that you want to use the new class as an actual widget, you need to use the register_widget function on the widgets_init action.

As you can see in the example below, the best place to add a new hook to widgets_init is within the function, executed on uf.init.

<?php
add_action( 'uf.init', 'showcase_include_widgets' );
function showcase_include_widgets() {
	require_once __DIR__ . '/Showcase_Accordion_Widget.php';	
	add_action( 'widgets_init', 'showcase_register_widgets' );
}

function showcase_register_widgets() {
	register_widget( 'Showcase_Accordion_Widget' );
}

Creating the widget

Here is the content of Showcase_Widget_Accordion.php:

<?php
use UF3\Custom_Widget;
use UF3\Container;
use UF3\Field;

class Showcase_Accordion_Widget extends Custom_Widget {
	public function __construct() {
		parent::__construct( 'accordion_widget', __( 'Accordion', 'showcase' ), array( 
			'classname'   => 'accordion-widget',
			'description' => __( 'A widget with multiple sections'. 'showcase' ),
		));

		Container::create( 'accordion_widget' )
			->add_location( 'widget', 'Showcase_Accordion_Widget' )
			->add_fields(array(
				Field::create( 'text', 'title', __( 'Title', 'showcase' ) ),
				Field::create( 'repeater', 'sections', __( 'Sections', 'showcase' ) )
					->add_fields(array(
						Field::create( 'text', 'title', __( 'Title', 'showcase' ) ),
						Field::create( 'textarea', 'text', __( 'Text', 'showcase' ) ),
					))
					->set_add_text( __( 'Add section', 'showcase' ) )
			));
	}

	public function widget( $args, $instance ) {
		if( empty( get_value( 'sections', 'widget' ) ) ) {
			return;
		}

		include __DIR__ . '/template.php';
	}
}

As you can see, in this implementation, we are only using two methods in the class:

  1. The constructor, which defines the widget and registers fields.
  2. The widget method, which displays the widget.

Defining the widget

In the __construct method we are using parent::__construct to define the details of our widget. The codex article clearly explains the purpose of every argument/option, but here is a summary of what the result is:

  1. The internal identifier of the widget is "accordion_widget".
  2. The title of the widget will be "Accordion".
  3. In the front-end, the widget will have a accordion-widget CSS class.
  4. We are providing "A widget with multiple sections" as the description of the widget.

Those are the basics of registering a new widget and you can use the code above as a template for your projects.

Adding fields

We are registering the fields for the widget immediately after defining it. This is possible without an additional add_action call, since we are already using the uf.init action to include the widget.

The only thing to point out is the location, which we are using for the container:

->add_location( 'widget', 'Showcase_Accordion_Widget' )

As you can see, the second argument for add_location must be the full class name of the widget.

Fields can be defined in the dashboard

If you are using the administration UI to define fields, you may use it to add fields to the widget throught he Widget location.

Displaying the widget

The widget method of our class is resposible for displaying the widget in the front-end. This method receives one important argument, called $args. The argument is an array, which defines the currently displayed sidebar.

Within the widget method, you can use 'widget' as the second argument of all *_value functions, like get_value and the_value. Ultimate Fields detects which widget is being currently displayed and is ready to provide the right values.

In this example we are checking if there are any sections for the container by checking empty( get_value( 'sections', 'widget' ) ). If there are no sections, we are bailing and not displaying a widget at all. When there are any sections already, we are proceeding with the template.php template, which contains the body of the widget.

<?php echo $args['before_widget'] ?>

	<?php if( get_value( 'title', 'widget' ) ): ?>
		<?php echo $args['before_title'] ?>
			<?php the_value( 'title', 'widget' ) ?>
		<?php echo $args['after_title'] ?>
	<?php endif ?>

	<?php while( have_groups( 'sections', 'widget' ) ): the_group() ?>
		<div class="widget-section">
			<h3 class="widget-section__title"><?php the_sub_value( 'title' ) ?></h3>
			<div class="widget-section__text">
				<?php the_sub_value( 'text' ) ?>
			</div>
		</div>
	<?php endwhile ?>

<?php echo $args['after_widget'] ?>

In the beginning of the template we are displaying $args['before_widget'] and $args['after_widget']. This will output the correct widget wrappers, based on the current theme.

Within the actual widget, we are checking if there is a title at all and if there is one, we are displaying it (by using the_value), while actually using the before_title and after_title arguments.

Clone this wiki locally