For those who don’t know, Elementor is an amazing page builder for WordPress. Super fast with some really nifty features. Check it out here.
Today I’ll run through how you can add your own custom elements into the sidebar. We’ll do a basic one that outputs some text along with some recent post titles.
This is what the new element will look like:
And this is what will happen when dragging this element onto the page:
I’ll wrap this up into a handy plugin at the end, nice copy-paste example for you to use.
Elementor does not have a developer API as such, so we’ll just be interacting with the Elementor function calls directly.
Step 1: Choose an Elementor icon
Elementor widgets look like this:
So we need to choose an icon for the new one we’re going to make. The easiest way is to pick one of the existing Elementor icons (you can use font-awesome, it’s just a little messy, I’ll cover that in another post).
Head over to http://bluejamesbond.github.io/CharacterMap/ and click Select Font then upload the wp-content/plugins/elementor/assets/lib/eicons/fonts/eicons.ttf file. You’ll see all the available icons:
I click on the icon I wish to use and take note of the “name” to the left. The one I’m using here is called “post-list”:
Step 2: Create a WordPress plugin to hold our Elementor widget
Here’s the code. Nothing special. It just hooks into elementor/widgets/widgets_registered and then includes our Elementor file. We do it this way so the theme can override this custom Elementor widget if it wants to (I do things this way so I can share a base plugin between all my themes and make individual theme tweaks if necessary).
<?php /** * Plugin Name: Elementor Custom Elements * Description: Custom element added to Elementor * Plugin URI: http://dtbaker.net/web-development/creating-your-own-custom-elementor-widgets/ * Version: 0.0.1 * Author: dtbaker * Author URI: http://dtbaker.net * Text Domain: elementor-custom-element */ if ( ! defined( 'ABSPATH' ) ) exit; // This file is pretty much a boilerplate WordPress plugin. // It does very little except including wp-widget.php class ElementorCustomElement { private static $instance = null; public static function get_instance() { if ( ! self::$instance ) self::$instance = new self; return self::$instance; } public function init(){ add_action( 'elementor/widgets/widgets_registered', array( $this, 'widgets_registered' ) ); } public function widgets_registered() { // We check if the Elementor plugin has been installed / activated. if(defined('ELEMENTOR_PATH') && class_exists('Elementor\Widget_Base')){ // We look for any theme overrides for this custom Elementor element. // If no theme overrides are found we use the default one in this plugin. $widget_file = 'plugins/elementor/my-widget.php'; $template_file = locate_template($widget_file); if ( !$template_file || !is_readable( $template_file ) ) { $template_file = plugin_dir_path(__FILE__).'my-widget.php'; } if ( $template_file && is_readable( $template_file ) ) { require_once $template_file; } } } } ElementorCustomElement::get_instance()->init();
Step 3: Create the custom Elementor widget
Now we create the custom Elementor widget. We put this into a my-widget.php file in the plugin folder. This file can also be placed / modified in the theme folder ‘wp-content/themes/my-theme/plugins/elementor/my-widget.php’
The magic here happens with the $this->add_control() calls. I won’t list all the available controls here. The quickest way is to find an existing widget that you like ( wp-content/plugins/elementor/includes/widgets/*.php ) and just copy/paste the relevant controls in.
In our widget here we’re only having a text input box and a drop down list:
<?php namespace Elementor; if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly class Widget_My_Custom_Elementor_Thing extends Widget_Base { public function get_id() { return 'my-blog-posts'; } public function get_title() { return __( 'My Custom Widget', 'elementor-custom-element' ); } public function get_icon() { // Icon name from the Elementor font file, as per http://dtbaker.net/web-development/creating-your-own-custom-elementor-widgets/ return 'post-list'; } protected function _register_controls() { $this->add_control( 'section_blog_posts', [ 'label' => __( 'Blog Posts', 'elementor-custom-element' ), 'type' => Controls_Manager::SECTION, ] ); $this->add_control( 'some_text', [ 'label' => __( 'Text', 'elementor-custom-element' ), 'type' => Controls_Manager::TEXT, 'default' => '', 'title' => __( 'Enter some text', 'elementor-custom-element' ), 'section' => 'section_blog_posts', ] ); $this->add_control( 'posts_per_page', [ 'label' => __( 'Number of Posts', 'elementor-custom-element' ), 'type' => Controls_Manager::SELECT, 'default' => 5, 'section' => 'section_blog_posts', 'options' => [ 1 => __( 'One', 'elementor-custom-element' ), 2 => __( 'Two', 'elementor-custom-element' ), 5 => __( 'Five', 'elementor-custom-element' ), 10 => __( 'Ten', 'elementor-custom-element' ), ] ] ); } protected function render( $instance = [] ) { // get our input from the widget settings. $custom_text = ! empty( $instance['some_text'] ) ? $instance['some_text'] : ' (no text was entered ) '; $post_count = ! empty( $instance['posts_per_page'] ) ? (int)$instance['posts_per_page'] : 5; ?> <h3>My Example Elementor Widget</h3> <p>My text was: <?php echo esc_html( $custom_text );?> </p> <h3>Some Recent Posts Here:</h3> <ul> <?php $args = array( 'numberposts' => $post_count ); $recent_posts = wp_get_recent_posts( $args ); foreach( $recent_posts as $recent ){ echo '<li><a href="' . esc_url( get_permalink( $recent["ID"] ) ). '">' . esc_html( $recent["post_title"] ).'</a> </li> '; } wp_reset_query(); ?> </ul> <?php } protected function content_template() {} public function render_plain_content( $instance = [] ) {} } Plugin::instance()->widgets_manager->register_widget( 'Elementor\Widget_My_Custom_Elementor_Thing' );
Step 4: Profit!
Feel free to try Elementor (and a couple of my basic Elementor addons) in the live Elementor demo available here: http://summerblog.theme-demo.net/
Code is on Github
The above code is over on Github, check it out here: https://github.com/dtbaker/elementor-custom-element
What’s next?
You can also add new controls to existing elements. For example: this is how you add a new select control to an existing Elementor widget.
These blog posts are soooo helpful. I haven’t found anyone else writing about Elementor development. Thanks man.
I have a question for you…
All of the widgets that come packaged with elementor make use of the global font settings.
But none of the widgets I create seem to inherit those styles. Is there a trick to getting my custom elementor widgets to inherit the global elementor font styles?
Not too sure sorry, is it still doing this?
I think it’s not working.
Got this: Fatal error: Call to undefined method ElementorWidgets_Manager::register_widget()
Ok figured out. just use Plugin::instance()->widgets_manager->register_widget_type( new Widget_My_Widget );
Yep there’s some more changes in the recent version too, check back soon.
Hi there! Thanks for sharing!
But since one of the latest updates the code should be slightly different.
In the widget class you should have a function like this:
`
public function get_name() {
return ‘my-widget-name’;
}
`
and
Plugin::instance()->widgets_manager->register_widget( ‘ElementorWidget_My_Custom_Elementor_Thing’ );
has been replaced by
Plugin::instance()->widgets_manager->register_widget_type( new Widget_My_Custom_Elementor_Thing() );
Cheers,
Marc.
Thanks!
Yep there’s been quite a few breaking changes recently. The latest version includes new hooks/filters that should prevent this from breaking in future updates. I’ll fix up this example so it works with the latest and greatest version shortly.
Cheers.
Great tutorial!
And it is posible to change add this featured for sell themes for example in themeforest?
There is not any legal issue with the license? because an official API option, is not it?
Thank for the tutorial!! it is very useful!
Yep it’s possible.
Hey, I want to add a dropdown to the section not just a widget. Is this possible?
Hey can you send a screenshot of what you’re trying to achieve?
Hi dtbaker,
Thanks for this good tutorial.
I have faced one issue related to the text and blog post limit are not changing when I am updating from admin.
After that I have compare code and found below in widget file.
We should replace
$custom_text = ! empty( $instance[‘some_text’] ) ? $instance[‘some_text’] : ‘ (no text was entered ) ‘;
$post_count = ! empty( $instance[‘posts_per_page’] ) ? (int)$instance[‘posts_per_page’] : 5;
by this
$settings = $this->get_settings();
$custom_text = ! empty( $settings[‘some_text’] ) ? $settings[‘some_text’] : ‘ (no text was entered ) ‘;
$post_count = ! empty( $settings[‘posts_per_page’] ) ? (int)$settings[‘posts_per_page’] : 5;
Means we need to use get_setting(); function for getting value.
Please let me know if I am wrong.
Thanks,
Sunil
Using get_settings() is the new correct way to get the instance values 🙂 I will update my demo code
Hi dtbaker Thanks for your tutorial. After reading your tutorial I try to build my own widget
I’m adding some additional widgets to the page builder and want to include custom javascript. I found the API for enqueueing javascript however ran into issues: https://github.com/pojome/elementor/blob/develop/docs/content/hooks/php-hooks.md#frontend-actions
The code works great when I view the page on the front-end, however when I create a new widget in the Elementor editor the javascript doesn’t load.
Is there code to enqueue JS per widget/element? I tried using wp_enqueue_script within the protected function render() {} which worked on the front-end but again didn’t work when viewing using the elementor editor.
Yes I’ve managed to enqueue js for a custom backend widget before. Cannot remember off the top of my head, I’ll hunt through some code and see if I can find out how I did it.
Hey Dave, I’ve gone through the above comments and the code and updated everything to make this work on the latest version of Elementor (at time of writing, 1.9.3). I’ve uploaded them to Github and made a pull request to your repo, but in the meantime everyone else can check it out on mine.
https://github.com/bcpurleigh/elementor-custom-element
I have also created a version of the above to create more than one custom widget within the same plugin, which I will be adding on to this soon.
Have a great day!
It’s just active plugin then show on elementor widget option. How to create Automatically add on elementor widget. Please help.
Hello,
First of al thanks for the GitHub snippet 🙂 Unfortunately if I enable the plugin the rest of the Elementor Pro controls disappear. The compleet “PRO-ELEMENTEN” header is gone.
Do you know why this is and how to fix this? Might be that the new version 2.0 is causing this?
Thanks,
Bjorn
Hey,
I’m trying to create basic widget with Elementor, following official docs. When following the developer documents to create a new widget, the following error is thrown
Fatal error: Class ‘Elementor\Widget_Base’ not found
Do you know how to fix that?
I’m stuck and don’t know where else to ask 🙂
Cheers.
Hi is there a way to add more than one widget?
Hi – Is there a way to create a widget (or plugin) that combines Elementor’s native datepicker and it’s native countdown timer so that a front end user could select a date on one page, and then have the countdown timer on another page (rather than setting the countdown timer’s paramenters from the back end).
I hope I’m not too late to the party. Using the current version from github I’m unable to get the widget to appear in the Elementor list. The code seems to expect the widget file in “plugins/elementor/my-widget.php” and it is definitely there.
However, “$template_file = locate_template( $widget_file );” returns nil, so the register_widget_type is never called.
What am I missing here ?
Hi! I am creating a custom plugin for my client site name “carousel for elementor”. I have added JS scripts which does’t show fine in live preview editor after editing any field. JS file run only first time on load page.
I know that the solution is In this page but not able to find out solution.
https://code.elementor.com/js-hooks/
Any idea?
can you tell how we can add custom css for all registered widgets like elementor pro feature?
I dropped in the plugin files under wp-content/plugins/elementor-custom-element
The plugin shows up in the plugins list, I active it ok, but I don’t see any new icon in elementor widgets list..
???
Hey there, just a quick question, is this still up to date?