How to create custom Elementor Widget in WordPress

elementor-widget
  1. What is Elementor
  2. What Is a Elementor Widget?
  3. Creating Custom Widget
  4. Registering Widgets
  5. Add ajax code to fetch image
  6. Register script to execute Ajax code
  7. Creating Widget functionality
    1. Widget Class
    2. Widget Methods
    3. Widget Data Methods
    4. Registering Controls
    5. Add Controls to Widget
      1. Elementor Tabs
      2. Media Control
      3. Image Size Group Control
      4. Textarea Control
      5. Color Control
      6. Typography Group Control
    6. Widget Rendering
  8. Download Full Code Plugin

What is Elementor

Elementor is the leading WordPress website page builder that give you ability to successfully build clean, professional, pixel-accurate websites. With an Elementor Widget intuitive drag and drop interface, you get complete control to build any type of website, without writing a single line of code.

What Is a Elementor Widget?

Elementor Widget refers to a small GUI application that is used for completing a specific task. Elementor have lots of useful widgets in the widgets panel. These widgets are divided into categories.

Creating Custom Widget

We will create a simple Elementor Widget that adds widgets to Elementor left side panel . it add title and image which load using ajax. below is folder and file structure.

elementor-module/
|
├─ widgets/
|  ├─ image-module-widget.php
|
├─ js/
|  ├─ module_img_script.js
| 
├─ img/
|  ├─ loading-icon.gif
|
└─ elementor-module.php

Create folder “elementor-module” in folder plugins in wordpress. next create file “elementor-module.php” in folder “elementor-module” and add below code.

plugins/elementor-module/elementor-module.php

<?php

/**
 * Plugin Name: Elementor Module
 * Description: Simple image load with ajax widgets for Elementor.
 * Version:     1.0.0
 * Author:      Elementor Module Developer
 * Author URI:  https://webdav.in
 * Text Domain: elementor-module
 */

function register_image_module_widget($widgets_manager)
{

	require_once(__DIR__ . '/widgets/image-module-widget.php');

	$widgets_manager->register(new \Elementor_Image_Module_Widget());
}
add_action('elementor/widgets/register', 'register_image_module_widget');


add_action("wp_ajax_module_img_fetch", "module_img_fetch");
add_action("wp_ajax_nopriv_module_img_fetch", "module_img_fetch");

function module_img_fetch()
{

	if (!wp_verify_nonce($_REQUEST['nonce'], "module_img_fetch_nonce")) {
		exit("No naughty business please");
	}

	$img_ids = $_REQUEST['img_id'];
	$module_img_size = $_REQUEST['module_img_size'];
	$i = 0;
	foreach ($img_ids as $img_id) {
		$response[$img_id] = wp_get_attachment_image($img_id, $module_img_size[$i]);
		$i++;
	}
	wp_send_json($response);
	die();
}

add_action('init', 'my_script_enqueuer');

function my_script_enqueuer()
{
	wp_enqueue_script('jquery');
	wp_enqueue_script('module_img_fetch_script', plugin_dir_url(__FILE__) . 'js/module_img_script.js', array('jquery'));
	wp_localize_script('module_img_fetch_script', 'moduleFetchAjax', array('ajaxurl' => admin_url('admin-ajax.php'), 'security' => wp_create_nonce('module_img_fetch_nonce')));
	wp_enqueue_script('module_img_fetch_script');
}

 



Registering Widgets

To register new widgets use the following code:

 

function register_image_module_widget($widgets_manager)
{

	require_once(__DIR__ . '/widgets/image-module-widget.php');

	$widgets_manager->register(new \Elementor_Image_Module_Widget());
}
add_action('elementor/widgets/register', 'register_image_module_widget');

We just connect to the elementor/widgets/register action which gives access to the widgets manager as a parameter. We can use the widgets manager to add new widgets using the register() method with the widget instance

Add ajax code to fetch image

add_action("wp_ajax_module_img_fetch", "module_img_fetch_func");
add_action("wp_ajax_nopriv_module_img_fetch", "module_img_fetch_func");

function module_img_fetch_func()
{

	if (!wp_verify_nonce($_REQUEST['nonce'], "module_img_fetch_nonce")) {
		exit("No naughty business please");
	}

	$img_ids = $_REQUEST['img_id'];
	$module_img_size = $_REQUEST['module_img_size'];
	$i = 0;
	foreach ($img_ids as $img_id) {
		$response[$img_id] = wp_get_attachment_image($img_id, $module_img_size[$i]);
		$i++;
	}
	wp_send_json($response);
	die();
}

1. add_action(“wp_ajax_module_img_fetch”, “module_img_fetch_func”) : This hook allows you to handle your custom AJAX endpoints. The wp_ajax_ hooks follows the format “module_img_fetch“, where “module_img_fetch” is the ‘action‘ field submitted to admin-ajax.php.This hook only fires for logged-in users.

2. add_action(“wp_ajax_nopriv_module_img_fetch”, “module_img_fetch_func”) : This hook only fires for non logged-in users. To allow both, you must register both hooks!

Register script to execute Ajax code

add_action('init', 'my_script_enqueuer');

function my_script_enqueuer()
{
	wp_enqueue_script('jquery');
	wp_enqueue_script('module_img_fetch_script', plugin_dir_url(__FILE__) . 'js/module_img_script.js', array('jquery'));
	wp_localize_script('module_img_fetch_script', 'moduleFetchAjax', array('ajaxurl' => admin_url('admin-ajax.php'), 'security' => wp_create_nonce('module_img_fetch_nonce')));
	wp_enqueue_script('module_img_fetch_script');
}

1. add_action(‘init’, ‘my_script_enqueuer’) : “add_action” are the hooks that the WordPress core launches at specific points during execution, or when specific events occur. “init” Fires after WordPress has finished loading but before any headers are sent.

2. wp_enqueue_script : it refers to registering and adding scripts to your site.

Creating Widget functionality

Create folder “widgets” in folder “elementor-module”. next create file “image-module-widget.php” in folder “elementor-module/widgets” and add below code.


 
<?php
class Elementor_Image_Module_Widget extends \Elementor\Widget_Base
{

	public function get_name()
	{
		return 'image_module_widget';
	}

	public function get_title()
	{
		return esc_html__('Image Module', 'elementor-module');
	}

	public function get_icon()
	{
		return 'eicon-image';
	}

	public function get_categories()
	{
		return ['basic'];
	}

	public function get_keywords()
	{
		return ['image', 'module'];
	}

	protected function register_controls()
	{

		$this->start_controls_section(
			'image_title',
			[
				'label' => esc_html__('Image', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'image',
			[
				'label' => esc_html__('Choose Image', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::MEDIA,
				'default' => [
					'url' => \Elementor\Utils::get_placeholder_image_src(),
				],
			]
		);
		

		$this->add_group_control(
			\Elementor\Group_Control_Image_Size::get_type(),
			[
				'name' => 'image',
				'default' => 'large',
			]
		);

		$this->end_controls_section();

		// Content Tab Start

		$this->start_controls_section(
			'section_title',
			[
				'label' => esc_html__('Title', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);



		$this->add_control(
			'title',
			[
				'label' => esc_html__('Title', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::TEXTAREA,
				'default' => esc_html__('Hello world', 'elementor-module'),
			]
		);




		$this->end_controls_section();

		// Content Tab End



		$this->start_controls_section(
			'content_section',
			[
				'label' => esc_html__('Content', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			[
				'name' => 'content_typography',
				'selector' => '{{WRAPPER}} .hello-world',
			]
		);

		$this->end_controls_section();


		// Style Tab Start

		$this->start_controls_section(
			'section_title_style',
			[
				'label' => esc_html__('Title Color', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'title_color',
			[
				'label' => esc_html__('Title Text Color', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .hello-world' => 'color: {{VALUE}};',
				],
			]
		);


		$this->end_controls_section();

		// Style Tab End

	}

	protected function render()
	{
		$settings = $this->get_settings_for_display(); ?>

		<input type="hidden" class="module_img_cls" value="<?php echo $settings['image']['id']; ?>" data-size="<?php echo $settings['image_size']; ?>" />

		<div class="module_img_div_<?php echo $settings['image']['id']; ?>"><?php echo $img_path = '<img src = ' . plugin_dir_url( __DIR__ ) . 'img/loading-icon.gif >' ?></div>

		<p class="hello-world">
			<?php echo $settings['title']; ?>
		</p>

<?php }
}



Widget Class

First, we need to create a class that extends the \Elementor\Widget_Base class:

class Elementor_Image_Module_Widget extends \Elementor\Widget_Base {
}

Widget Methods

A simple widget skeleton class will look as follows:

 
class Elementor_Image_Module_Widget extends \Elementor\Widget_Base {

	public function get_name() {}

	public function get_title() {}

	public function get_icon() {}

	public function get_categories() {}

	public function get_keywords() {}

	public function get_custom_help_url() {}

	protected function get_upsale_data() {}

	public function get_script_depends() {}

	public function get_style_depends() {}

	protected function register_controls() {}

	protected function render() {}

	protected function content_template() {}

}

Widget Data Methods

Widget data needs to be “returned” by certain methods. Those methods are simple:

 
<?php
class Elementor_Image_Module_Widget extends \Elementor\Widget_Base
{

	public function get_name()
	{
		return 'image_module_widget';
	}

	public function get_title()
	{
		return esc_html__('Image Module', 'elementor-module');
	}

	public function get_icon()
	{
		return 'eicon-image';
	}

	public function get_categories()
	{
		return ['basic'];
	}

	public function get_keywords()
	{
		return ['image', 'module'];
	}
}

Name : The get_name() method returns the widget name as it will be used in the code.

Title : The get_title() method returns the widget label as it will be displayed to the user.

Icon : The get_icon() method is an optional, but recommended, method. It lets you set the widget icon. You can use any Elementor icons (opens new window)or FontAwesome icons (opens new window), to simply return the CSS class name.

Categories : The get_categories() method lets you set the category of the widget.

Keywords : The get_keywords() method lets you set widget keywords and is used to filter the widget list.

Registering Controls

In your widget class, you can add controls inside the register_controls() method as follows:

 
class Elementor_Image_Module_Widget  extends \Elementor\Widget_Base {

	protected function Elementor_Image_Module_Widget () {

		$this->start_controls_section();

		$this->add_control();

		$this->add_control();

		$this->add_control();

		$this->end_controls_section();

	}

}

Add Controls to Widget

below, we’re going to add a few controls to a widget to allow users save data:

 class Elementor_Image_Module_Widget  extends \Elementor\Widget_Base { 
protected function register_controls()
	{

		$this->start_controls_section(
			'image_title',
			[
				'label' => esc_html__('Image', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'image',
			[
				'label' => esc_html__('Choose Image', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::MEDIA,
				'default' => [
					'url' => \Elementor\Utils::get_placeholder_image_src(),
				],
			]
		);
		

		$this->add_group_control(
			\Elementor\Group_Control_Image_Size::get_type(),
			[
				'name' => 'image',
				'default' => 'large',
			]
		);

		$this->end_controls_section();

		// Content Tab Start

		$this->start_controls_section(
			'section_title',
			[
				'label' => esc_html__('Title', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);



		$this->add_control(
			'title',
			[
				'label' => esc_html__('Title', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::TEXTAREA,
				'default' => esc_html__('Hello world', 'elementor-module'),
			]
		);




		$this->end_controls_section();

		// Content Tab End



		$this->start_controls_section(
			'content_section',
			[
				'label' => esc_html__('Title Typography', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			[
				'name' => 'content_typography',
				'selector' => '{{WRAPPER}} .hello-world',
			]
		);

		$this->end_controls_section();


		// Style Tab Start

		$this->start_controls_section(
			'section_title_style',
			[
				'label' => esc_html__('Title', 'elementor-module'),
				'tab' => \Elementor\Controls_Manager::TAB_STYLE,
			]
		);

		$this->add_control(
			'title_color',
			[
				'label' => esc_html__('Text Color', 'elementor-module'),
				'type' => \Elementor\Controls_Manager::COLOR,
				'selectors' => [
					'{{WRAPPER}} .hello-world' => 'color: {{VALUE}};',
				],
			]
		);


		$this->end_controls_section();

		// Style Tab End

	}
} 

start_controls_section() creates a new section.

end_controls_section() closes the section.


Every control has the following key parameters:

Section Name (string) – Unique id used in the code.
Section Setting (array) – Extra section parameters.
Label (string) – Label displayed to the user in the panel.
Tab (string) – Tab where the section is located. Default is content.
Conditions (array) – Control display conditions.

Elementor Tabs

Elementor uses tab navigation to display controls. When extending Elementor, you can use any tab you need, or create new ones.

Built-in Tabs

Elementor has 6 pre-defined tabs used in different panels:

Name/ID Label Constant
content Content \Elementor\Controls_Manager::TAB_CONTENT
style Style \Elementor\Controls_Manager::TAB_STYLE
advanced Advanced \Elementor\Controls_Manager::TAB_ADVANCED
responsive Responsive \Elementor\Controls_Manager::TAB_RESPONSIVE
layout Layout \Elementor\Controls_Manager::TAB_LAYOUT
settings Settings \Elementor\Controls_Manager::TAB_SETTINGS

In displays controls in a Content tab, allowing the user to set the widget content, and a Style tab to design the content. In addition, Elementor adds an Advanced tab to all widgets.


Media Control

Elementor Media control displays a media chooser section based on the WordPress media library.

When using this control, the type should be set to \Elementor\Controls_Manager::MEDIA constant.

Arguments

Name Type Default Description
type string media The type of the control.
label string The label that appears above of the field.
description string The description that appears below the field.
show_label bool true Whether to display the label.
label_block bool true Whether to display the label in a separate line.
separator string default Set the position of the control separator. Available values are default, before and after. default will hide the separator, unless the control type has specific separator settings. before / after will position the separator before/after the control.
media_types array [‘image’] Supported media types. Available values are image, video, svg, application/pdf etc.
default array Default media values.

  • $id (int) Media id.
  • $url (string) Media url.


Image Size Group Control

Elementor image size group control show input fields to define one of the default image sizes like thumbnail, medium, medium_large, large or custom image dimensions

The control is describe in Group_Control_Image_Size class which extends Group_Control_Base class.

Arguments

Name Type Default Description
type string image-size The type of the control.
separator string default Set the position of the control separator. Available values are default, before and after. default will hide the separator, unless the control type has specific separator settings. before / after will position the separator before/after the control.
include array Image sizes to include.
exclude array Image sizes to exclude.
default string The default image size.

Textarea Control

Elementor textarea control displays a classic textarea field with an option to set the number of rows.

When using “Textarea Control” , the type should be set to \Elementor\Controls_Manager::TEXTAREA constant.

Arguments

Name Type Default Description
type string textarea The type of the control.
label string The label that appears above of the field.
description string The description that appears below the field.
show_label bool true Whether to display the label.
label_block bool true Whether to display the label in a separate line.
separator string default Set the position of the control separator. Available values are default, before and after. default will hide the separator, unless the control type has specific separator settings. before / after will position the separator before/after the control.
rows int 5 Number of rows.
placeholder string The field placeholder that appears when the field has no values.
default string The field default value.


Color Control

Elementor color control displays a color picker field with an alpha slider. It includes a customizable color palette that can be preset by the user.

When using this control, the type should be set to \Elementor\Controls_Manager::COLOR constant.

Arguments

Name Type Default Description
type string color The type of the control.
label string The label that appears above of the field.
description string The description that appears below the field.
show_label bool true Whether to display the label.
label_block bool false Whether to display the label in a separate line.
separator string default Set the position of the control separator. Available values are default, before and after. default will hide the separator, unless the control type has specific separator settings. before / after will position the separator before/after the control.
alpha bool true Whether to allow alpha channel.
default string Default color in RGB, RGBA, or HEX format.


Typography Group Control

Elementor typography group control displays input fields to define the content typography including font size, font family, font weight, text transform, font style, line height and letter spacing.

When using this group control, the type should be set to Group_Control_Typography::get_type() method.

Arguments

Name Type Default Description
type string typography The type of the control.
separator string default Set the position of the control separator. Available values are default, before and after. default will hide the separator, unless the control type has specific separator settings. before / after will position the separator before/after the control.
exclude array Exclude some controls from the group control. Example: [‘font_style’]


Widget Rendering

The last step in Elementor Widget development is to display the output. Each widget needs to render the data returned from the controls, and generate the final HTML displayed in the frontend and the preview area.

class Elementor_Image_Module_Widget extends \Elementor\Widget_Base
{ 
protected function render()
	{
		$settings = $this->get_settings_for_display(); ?>

		<input type="hidden" class="module_img_cls" value="<?php echo $settings['image']['id']; ?>" data-size="<?php echo $settings['image_size']; ?>" />

		<div class="module_img_div_<?php echo $settings['image']['id']; ?>"><?php echo $img_path = '<img src = ' . plugin_dir_url( __DIR__ ) . 'img/loading-icon.gif >' ?></div>

		<p class="hello-world">
			<?php echo $settings['title']; ?>
		</p>

<?php }
}

Rendering Methods

Elementor has rendering method, depend on the returned values from the control.

render() – It is written as a PHP template that generates output in the frontend.

Download Full Code Plugin

Download

Suggested post : How to Create WordPress Widget

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top