Creating Layers Builder Widgets

Child Theming, Extension Development

Since: 1.2.4 Last Updated: for: 1.6.5 Time to Read: 33 minutes

When we refer to creating a widget, we are referring to the widgets that are used in the Layers Builder pages, which include specialized Layers controls such as the design bar.

The primary difference between the Layer Builder Widget creation process and a standard widget is that builder widgets require extending the Layers_Widget class, and use several helper functions from the Layers framework for building controls.

For more information on standard widget creation, which works from both themes and plugins, be sure to read the following tutorial on Tuts+. Introduction to Creating Your First WordPress Widget.

In this tutorial we will walk you through the structure of a Layers widget, referencing the Layers Post widget to create a custom version that looks at a custom post type. This is normally used in combination with a Plugin. If you are creating a widget in a Child Theme, you may use this tutorial to understand the structure in the core widgets so you are able to easily adapt the Content Widget to your needs.

We recommend choosing one of the core widgets to start with, then use this guide to supplement the code comments to learn more about what each code block is for.

Reference: View Layers Widget Structures here

The widget code structure itself is almost identical to a standard WordPress widget. However, you will notice we call several Layers-specific functions and begin with extending the Layers_Widget PHP class , which enables us to use helper functions that we’ve added to Layers to speed up widget creation.

Here is the basic layout of a Layers widget file:

Widget File Header

The first thing to do is give your widget class a unique name, where we define
Your Widget Name
Example:
Layers Stories Widget
We recommend keeping to the “Layers” + “Widget Name” convention to help users locate the widgets easier in the Customizer.

Your widget must have a unique PHP class name, which consists of capitalized words separated by underscores.

Example:
My_Layers_Stories_Widget

It is really important to put a unique prefix on the class here to avoid conflicts with another theme or extension that happens to load the same class name. Change the class of the example code to reflect your project, ie My_Layers_Stories_Widget.

We wrap this in a condition as a further safety measure so it doesn’t collide with another instance of the class (which is why it is important it have a unique name!)

The first thing inside our widget class is our widget function, which constructs the widget by setting up some basic rules and defaults.

Create a function for your class or edit the demo code. This should match the class name.

Set Variables

You will now add all the local scope variables  inside this function. Each of these variables is prefixed by $this-> which sets up each instance of these variables so the widget can be used multiple times.

Using the Posts widget from the Layers core as a guideline, this is how our variables would look for a custom widget used to display a Custom Post Type called layers-demo-posts

Each variable is explained below:

Widget Title

$this->widget_title;
Accepts a text argument that must be wrapped in __()
__('Title', 'layerswp');
This variable sets the title of the widget inside the customizer. We recommend retaining the layerswp textdomain here to make translation easier for those using translation plugins.

Widget ID

$this->widget_id;
This value should be a unique name which is used only for the widget you area creating i.e .
'myplugin-features'

Post Type

$this->post_type;
We declare the post type being used in the Posts widget so that there’s no confusion later on (for example when using
WP_Query()
). If you are constructing a widget for a custom post type, this would be the post type, such as
'layers-doc'
as we use on this site.

If you are not querying post objects, such as in creating a content or slider-type widget, you would leave this blank i.e.
$this->post_type = '';

Category & Taxonomy

$this->taxonomy;
The same way we declare the post type to be used, it’s easier to declare your taxonomy up here than remember it over and over.

The default taxonomy for posts in WordPress is 'category'

. If you will be querying posts and categories in your widget and want to use a custom post type, replace this value with your custom taxonomy name, i.e. 'topic'

is our custom taxonomy for the layers-doc post type.

If you are not querying post objects, such as in creating a content or slider-type widget, you would leave this blank i.e.
$this->taxonomy = '';

Display Options

$this->checkboxes;
Our Posts widget presents several options for the user in the form of check-boxes under the Design Bar’s Display button, such as Show Dates or Show Tags. These options can be used in a variety of ways or be housed under a custom design bar button, or left out of your widget entirely. In our Posts widget, they are used to control the visibility of various elements of the post.

In order to sanitize our check-boxes in the save function, we declare them here. Each item in the array is the id of the check-box to be used in our form later on.

If creating a widget that queries posts, you may include all or only the values in the array that relate to your project.

For custom post types, you can setup unique options here that correspond to custom fields, or use the pre-existing ones to access core meta such as the title, date, etc when setting up your custom Design Bar options. We want to allow users to show or hide the Photo Credit or Topic setup in our custom post type meta and taxonomy, so we add

show_credit and show_topics to replace show_tags and how_categories you find in the default Posts Widget. These option keys will be used later when setting up our Design Bar Display options.

If your widget does not query posts, such as a widget based on the Content Widget, you can leave this blank, i.e.
$this->checkboxes = array();

Widget and Control Ops

$widget_ops  and $control_ops  are globals which allow you to set things like your widget’s CSS class, description, fixed height or width, etc.

'classname' = Prefixing the value with 'obox-layers-'  will add the Layers badge to the widget. You can copy the entire value in the example above to generate this class based on your widget ID 'description'  = takes a text string and should be wrapped in __()  to support localization.

'width'  = Takes a number in single quotes corresponding to pixels. This is optional, but 660 ensures the widget design is consistent with other Layers widgets.

'height'  = Takes a number in single quotes corresponding to pixels. Define this only if your widget requires a fixed height, otherwise leave NULL

'id_base'  = This sets a base for the widget ID, which is generated automatically. If you use our default value, it will output layers-widget-post , for example.

Note: We use the constant LAYERS_WIDGET_WIDTH_SMALL  in the Post Widget, however you won’t be able to call these constants from a plugin (but can make your own). This constant translates to 660 pixels, which is the standard Layers widget width setting. The height is set to NULL as we want our widget to span the entire screen height.

Putting all of the above together, we can safely instantiate our widget. This example complies with the WordPress 4.3 constructor requirements. You do not need to change anything about this line.

Widget Defaults

In the final part of our constructor, we set up our option defaults array. Since our widget functions just like a Post Widget, we can start with the defaults as they are defined in that widget file. We have already determined we will not have a Show Tags or Show Category option, so we can replace those option keys with our custom ones, show_credit  andshow_topic, which will correspond to custom checkboxes in the Display option of our widget’s Design Bar. Essentially your defaults setup each option key in the widget with a default value, following the 'option_key' => 'value', syntax.  The kind of value these option keys accept is defined by you later on and can be updated here if you change your mind.

The next section of your class sets up the instance of your form which houses all of the option fields.

A Layers widget form consists of two main areas. The first area (1)  is our Design Bar, which offers the layout and styling control in the widget that makes it so great.

The second area is what we call the ‘canvas’ area or which holds the settings specific to this instance of the widget content and their respective content options form elements (2 & 3)

This is a free-form area which can be used in any way you please, as it accepts plain HTML and PHP, allowing full creative freedom inside the widget (a good example of this are our own content and slider widgets).

With that in mind, let’s move onto the code…

design-bar

Widget Design Bar

The first action we take in our form is to grab the widget defaults (set in our construct) and extract the values from
$instance
You don’t need to do this but we find it easier to work with variables than with a large array. Your defaults start where “Form Elements go here” is shown in the example code above, by setting up some variables. These can be carried over as-is.

Next up we setup our Design Bar components. For more information on the different standard Design Bar components see Anatomy of the Design Bar

Inside our $design_bar_components  array, we will define the following components. You can leave one out if you don’t need it, or create your own custom component key here. Below is a overview of what our chosen component keys relate to.

layout  – Full Width / Boxed.

fonts – Font size / alignment, in this case it will apply to the widget Title & Excerpt.

custom – This indicates the placement of our custom components which we’ll unpack in the next section

columns  – How many columns we will display.

liststyle – This gives us the option of Masonry, Grid or List (standard blog list in this case).

imageratio - This will apply to our posts’ featured images.

background – This controls the background of the entire widget.

advanced- This will add our custom CSS control as well as margin & padding settings.

Note that we pass the components through a filter withapply_filters  so that other developers can hook into the setup, such as a Child Theme developer that wants to build a theme around your plugin but not allow the Advanced option. Filters are not required for the widget to work, but are encouraged.

Inside our$design_bar_custom_components   array, we can define all of our special option keys.

These custom elements allow us to specify our own controls which aren’t predefined by the Design Bar. In this case, it includes display check-boxes and text inputs. It’s important to note that this element is an array inside an array, which allows us to have more than one custom pop-out menu.

We start with the Display options  $design_bar_custom_components  defined in the Post Widget, but removeshow_tags and show_category and replace them withshow_credit and show_topics to work with our custom post type taxonomy and meta (remember we set these up in our checkboxes instance in the main function).

Let’s investigate the array on Line 4:

Beginning with the array key, we use 'display'  as these elements will control how content is displayed in the widget.

Each design bar option array contains the following:

icon-css- This is a CSS class used to display the pop out icon. Refer to the following for a detailed overview of the Layers Icon Set

label- Accepts a text argument that must be wrapped in

__() for localaization support.  Example:

__('Display', 'layerswp');

elements- An array containing the custom elements which will be shown inside the pop out.

Within the elements  array on Line 7 is where we can define our form fields by referencing the input types listed in the input() helper function. In the demo widget and code example below, we remove the show_tags  and show_categories elements and replace them with show_credit  and show_topics  to work with our custom post type taxonomy and custom meta.

The Display option in the Post widget already defines several elements  we can copy in after this and then modify if needed. Reference them here.

Gives us the following:

widget-display-options

Remember earlier where we said that we’ll extend the Layers_Widget  PHP class so that we can use helpers? Well this is the first time we’ll be using one of those helpers,

$this->designbar();, which instantiates the Design Bar.

The following options are set in this instance and do not need to be changed or customized for your widget.

side-  sets the ‘side’ CSS class to ensure the bar is positioned on the side of the widget. Don’t change this!

id  andname  – These are the Design Bar form name and ID fields. For the purpose of this widget type, we use 'design'. If you reference the Slider or Content Widget, you will see different values here such as design-liststyle. Don’t change them!

$instance- We pass through the widget $instance so that we can grab values from it.

$design_bar_components- Our standard Design Bar components as defined above.

$design_bar_custom_components- Our custom Design Bar components as defined above.

As we mentioned before, your ‘canvas’ area is free-form (the area where the content of the widget is configured), but you may still use the Layers_Form_Elements Class to register your form elements.

The entire body of the widget to the left of the Design Bar is created with the .layers-container-large wrapper.

In a widget which intends to display a post type and give the user some options for customizing the category and number of posts, etc, you only need two primary sections, the widget header and the form elements themselves.

Widget Header

This is the blue bar across the top of the widget which houses the widget’s admin title and the Remove/Close buttons.

Create it using the built-in
header()
helper function. We instance it with the following syntax which sets the instance variable, and calls the form_elements class with the header helper:

This accepts the following parameters inside the helper array:
title
Accepts a text argument that must be wrapped in  __(). e.g.
__('Title', 'layerswp');
This variable sets the title of the widget inside the customzier, and appears in the blue bar at the top of the widget config panel. The second argument is your textdomain.

Using ‘layerswp’ is OK.

icon_class Will automatically be prepended by layers-icon- . A list of icon classes can be found in the Framework Reference.

Underneath our widget header and before the closing </div>  of the layers-container-large  wrapper,  we will add the Widget Title/Description Heading fields (2) and the content options (3).

Always include the Title/Description form in your widgets!

canvas-area

These are wrapped in a pair of framework wrappers and classes which will allow your form elements to style correctly. You do not need to worry about adding a

<form> or <fieldset>

element here!

Each form element inside this should be wrapped in
<p class="layers-form-item">
as noted in the input() reference. Below is a summary of the elements in our Post Widget which we will adapt for our widget:

Widget Title and Description

The first two we add are the widget Title and Excerpt which create the widget title and description shown above the posts on the front-end.

To define the field, the form_elements()->input helper is used, which accepts the following parameters:

We want a simple text field and textarea, so we give them a value of ‘text’ and ‘textarea’. Accepted values correspond to standard HTML form-element types such as text , etc.

name and id

We have already defined some shortcuts back in our widget construction that we can use here, $this->get_field_name( ‘title’ )helps keeps things consistent.

Accepts a text argument that must be wrapped in a gettext call and creates the text shown inside the text field by default before a user clicks into the field, best used to provide a tip on what the field is used for. Example:

value

We want the title to reflect what the user types in, so we set the value to the $title variable, already defined in the Layers_Widget PHP class.

class

Sets the CSS class to use for styling the field in the widget. For text fields, this is layers-text . For rich-text fields or textareas, this is layers-textarea. The layers-large class is added to define the icon size.

 

Category To Display

The next option we want is a drop-down to allow filtering content by Topic, which is our custom post type’s version of a category. To do this, we must loop through get_terms()  to populate a our options array, which looks at our custom taxonomy layers-demo-category which we already defined during widget construction above.

We can set a custom default label on Line 5, and a default to represent All categories on Line 6 in the $category_options[0] variable.

We then instance another input on Line 8. In the input instance, we set a new field ‘type’ of ‘select’ and set out ‘name’ and ‘id’ to grab the category value selected from the list generated by our terms query.

 

Number of Items to Show 

Instance another input, but this time give it a ‘type’ of ‘number’. This allows for setting some additional parameters, such as a minimum  (‘min’ ) and maximum (‘max’ ) value, or a step value, if needed.

Sort By and Sort Order

You should always allow for sorting of queried content. You can do this with another input instance that sets a ‘select’ type. In our sort option, we use a helper from the Form Class called
get_sort_options
as the ‘options’ value. This helper returns an array of sort options like “Newest First” that gives us two options in one, the order and orderby parameters.

 

Here is a sneak peek at the final widget form:

demo-widget-form

Note you wont see the widget in your customizer until you initialize and register it later.

The
update
function beginning on line 275 of the Post widget, for reference, is the third thing we setup in the widget class. It takes our checkbox settings and ensures they update the selected status as the user sets each option. You do not need to change/customize this function.

That’s it for the back-end!

The widget front end is where we edit how the widget is rendered when the page is viewed in the browser. We utilize many more of theLayers_Widget PHP class helpers in this
widget
function, making this example great for getting used to the way we put our widgets together. All of your markup will go inside the widget function in section 4 of the widget layout.

To celebrate making it this far in the tutorial, get up and make another cup of coffee!

As each code section is explained, we will point out where you can define custom values or change something. We are building from lines 93-351 of the Post Widget, broken down into manageable chunks below:

Setup

Let’s start with the initial extraction of the elements defined in the widget options.In this example, we’ve translated $instance  to $widget to be more semantic. The outline of this section is simple, beginning with an extract, setting a default variable, deciding whether to use it or not, then parsing the widget config. You don’t need to change anything here.

On Line 8 above, we look for an empty $instance in which case we use the widget defaults. That really helps users when first adding the widget to their page.

Check All The Things

Next up we go straight into a helper function. This time, we’re using an instance of check_and_return();  , which takes an argument and checks it against isset() , ensuring the option is not blank,  and allows us to check variables up to 4 levels deep.

Now we check our Layout and decide whether or not to enqueue Masonry (i.e. does the user have the Masonry grid style selected?)

Defining the Grid

The next function we perform is setting the column widths, which refer to the Layers Grid Framework classes.

Line 2-4 sets a fallback for the one-column class
span-12
Lines 5-7 demonstrate a shortcut for generating the class depending on the number of columns selected in the Design Bar option

Lines 8-10 set a default of 3 columns and its associated class. You can set a different number/class if you wish. Remember to update your widget defaults array in your main function if you do!

Colors and Font Settings

Time for more helpers! This time,  the helpers are going to allow us to automatically generate inline CSS according to our background and font setting choices. The function we will use is
layers_inline_styles();
Line 2: A condition to check the relevant Design Bar option

Line 3: Here we use
layers_inline_styles()
to take the value of our design controls and apply it to a specified selector. This function builds the required CSS for each Layers widget in the page as it is being influenced by the user’s choices. Once compiled it is output in the site footer as a performance measure.

This function needs the following arguments, shown below one per line:

Line 4 : Parent selector – The containing element we are targeting. By default this is an automatically generated widget ID via
$widget_id
. We recommend keeping it this way so users can properly create anchor links.

Line 5: CSS property – The property to set.  For more information on the different types of CSS available, see layers_inline_styles

Line 6: An array including our selectors and property values – In this case we are using background and color properties, and our selectors, such as those in the colors example,  are standard CSS selectors which will target the corresponding element inside our parent element.

In general, this should be carried over as-is to correspond to the controls in the Design Bar options if you have included the background and font color options in your Design Bar setup. If you have created additional color options, you would setup one layers_inline_styles() function for each option key to set its parent selector and CSS property.

Get Advanced Styles

The following function will generate our advanced styling for us. This includes our Advanced CSS Class and CSS, margin, padding and any other extended options added in the future or by other extensions.
// Apply the advanced widget styling $this->apply_widget_advanced_styling( $widget_id, $widget );

Featured Images

In the next block of code we pass our image settings through
 layers_translate_image_ratios();
. This function takes our Image Ratios option and returns the Layers-specific image ratio suffix. This grab the appropriate image crop and CSS classes and apply them to the featured image assigned to the post. You should insert this code as-is with no modification.

Query and Display Post Content

In order to display our custom posts in the widget, we need to build a custom query.

 

Lines 5-12: This is a standard way to setup pagination via
$paged
as you would use in a custom page template. Reference

Lines 14-16: These two variables set the post type and posts per page to grab the option value of
$this->post_type
 and your widget content form’s

posts_per_page
 

argument. You don’t need to change these unless you changed the option key names.

Lines 18-24: The $decode_order variable is where we take our single order  input, defined back in the Sort By section of our back-end form, and translate it into two options: Order and Order By. Neat!

Lines 28-38: The $tax_query argument is always a two-leveled array to allow  you to query more than one taxonomy at a time (and actually opens the option up to add tags or multiple taxonomies to this widget, if desired). Refer to wp_query for the basics of this array and other arguments accepted here. We left our category option as

'category', and defined the taxonomy to query in our instance of the taxonomy variable back in the beginning of the plugin class.

Line 41: Merges the arguments and sets up the new query. We will be modifying our post loop with the $post_query variable in just a bit.

Get Meta Data

We want our users to have control over the post meta that is displayed, so we populate an array with our Display option keys and the associated meta field key. These will be used later in a helper function called
layers_post_meta();
Note that we use isset()  here again as a safety measure so the data is only queried if the option is enabled.

Line 3:
date
pulls in the core Date Created time stamp on the post.

Line 4:
author
pulls in the author of the post

Line 5:
categories
will grab the categories (setup as topics for our post type) the post is assigned and output them in a comma-separated string.

In How to Add Custom Fields to Posts and Pages, we created two custom fields on our custom post type. One for a Photo Credit name and one for a Photo Credit URL that we can display under the Featured Image in our widget and in the post templates. These will be grabbed later inside the loop.

Now that we have setup a whole host of parameters, let’s start putting the HTML together.

Note that the original structure, helpers, hooks and classes should be retained in your custom builder widgets to ensure proper linkage with the framework and widget options. You may inject custom classes or HTML but should not change the existing, with special care given to the default classes and the HTML element types used.

Layers Builder widgets are each wrapped in a few <div>  tags using specific classes and class constructors, which should be retained. In brief it opens like this (Reference):

Class Constructors

We  use the
check_and_return
helper again, this time going two levels deep to verify our own custom CSS class for this widget, if set in the Advanced option. We also make use of the
get_widget_spacing_class()
helper which will apply our margin and padding. This is required if you want this Design Bar option to work! (Reference)

 

From here  it is almost exactly like writing a template, where each of your input values is output or checked using
$widget['value']
syntax.

Title & Description

The first block of code inside this wrapper  is used to display the widget’s Title and description. We also apply the settings from the Text option in the design bar to affect the size and alignment of text in this block. At a minimum, the title wrapper must define the
section-title
class ahead of this, but you can also add custom classes.

Widget Content

In the body portion of our widget, we use an instance of the
get_widget_layout_class()
helper on the
<div>
wrapper, which translates our layout selection into the correct class for the widget (that is the Full Width / Boxed Layout option).

The Post Loop

Since this is a standard post widget, we will be using the
WP_Query
argument  variable we setup earlier in a standard loop.  It begins simply like this:

Grid or List?

The first if()  statement checks to see if we’ve chosen to display our posts in the List layout, and if so returns that loop.

Refer to Lines 271-312 of the Posts Widget to see the basic structure of this layout markup. The only uniquely Layers part of the code is the layers_post_meta()  function which is a helper function that returns our standard post meta according to the options that we have defined above with
$layers_post_meta_to_display
. This is followed by a custom code block  to grab our custom meta field values and display them if the Show Credit option is checked.

This example shows how we have added our custom meta values to be output right after the standard meta we pull in with
layers_post_meta()
(line 262). We will use this again to modify the column style layout loop next.

If we are not using the List layout, then the Grid or Masonry layouts apply. Refer to Lines 314-371 of the Post Widget for the basic structure.

There are a host of classes that we apply to the
<article>
wrapper of this layout to ensure the column settings and responsive styling apply. The following explains what these variables do:

 
$widget['design'][ 'gutter' ]
– if we uncheck the gutter option in the Display option of the design bar, we add the
-flush
suffix to the
column
class. This will cause the post blocks to sit right up next to each other with no margin.
$span_class
– As defined above, this will let our grid know how many columns to display.
<?php if( 'overlay' == $this->check_and_return( $widget , 'text_style' ) ) echo 'with-overlay'; ?>

 If we’ve chosen Overlay for our Text & Excerpt position, then we will apply the

with-overlay
class.

Here is what it looks like put together:

 

Again we can insert our custom meta code block right after
layers_post_meta()
(Reference). This must be inside the
check_and_return
condition:

 

Line 2: Note that we have appended a custom class
meta-credit
to the classes we want the text option’s Invert rule to apply to. This ensures our custom meta gets the same treatment as the normal meta.

Line 10: We make sure to set our custom class on the meta value’s wrapper. We are mimicking the framework meta markup here by using the
meta-info
span.

Don’t forget to close everything up!

Pagination

Just after the closing
</div>
of our widget row, we need to sneak in the pagination. If you are creating a widget based on the Slider or Content Widget, this can be skipped.

First we check for the Show Pagination option in the Display Setting on the Design Bar. If it is checked, we will output the page links. We use the
container
class here to ensure automatic margins and spacing.

Next we use the
layers_pagination()
function to output the framework’s pagination. In general, you can use this block as-is.

 

Here is an example of the outcome:

demo-widget-overlay-meta

But what about Masonry?

If you recall at the beginning of this tutorial, we used a function called
enqueue_masonry()
. This function will get masonry to trigger on our widget so it is only loaded where it is used.

allows us to easily add masonry to any block of HTML. We use the
layers_masonry_settings[]
object to pass multiple PHP settings to our masonry function.

Just to be safe, we want to use wp_reset_postdata() before closing up our
widget( )
function.

To get the widget to show up in the Customizer at all, you need to register it using the Core WP register_widget function, which takes one simple argument, the name of your new widget defined at the beginning in your widget class.

You will need to initialize your widget via the WP core hook widgets_init, or it simply won’t show up in the customizer. We can do this via the plugin class, or a child theme’s functions.php. The format is slightly different depending on your project, and the priority value inside the action is critical if attempting to load widgets from a child theme.

Extension

If you have followed the guide from end to end, you should already have a hook  inside the plugin class constructor.  See Setup Your Plugin Class

The important bit here is 'register_widgets' , which refers to our custom function, and the priority 50 which ensures our widgets load after the Layers widget class has loaded. You may need to increase this if overrides are not working.

In Including Scripts, Styles & Helper Files, we cover how to create a custom
register_widgets
function to include our widget files via require_once()  function

Child Theme

When adding widgets to child themes, you need to wrap the whole thing in a custom function.So where we have the following at the beginning:

You must add a new first line using a unique function name. Example:

After the closing of your widget class, you can add the register_widget function and init hook:

The important bit here is the priority of 40 in your action, which ensures your widgets load after the core Layers widget class has loaded. This can be increased if you find overrides still not taking effect.

Ajax and Repeatable Fields

If you are creating a widget that uses columns or slides that users need to add dynamically, such as our Slider or Content widget, you must include helper functions to handle duplication of the last slide/column and enqueue the supporting script.

Use this example to support column duplication in a Content Widget type widget:

 

Line 1: Create a hook using wp_ajax prefix on a unique name.  Example: wp_ajax_your_action_name

This hook allows you to create custom handlers for your own custom AJAX requests. The wp_ajax_ hook follows the format
wp_ajax_$youraction
, where $youraction is your AJAX request’s 'action' property.

Line 3: Create your function

Line 7: Set
$widget
to a new instance of your widget class.

You will then need to enqueue a copy of the appropriate script, ie stories.js

Note that we use a LAYERS_VERSION constant here which you must have set in your functions to work. It outputs the Layers version at the end of the script URL when output in the front-end markup.