How to Create a Carousel Custom Widget in Elementor
Creating a custom Elementor widget is similar to creating a native WordPress widget.
Creating a New Widget
Creating a custom Elementor widget is similar to creating a native WordPress widget in that you start by creating a class that extends the Widget_Base class and filling in all of the required methods.
A unique name that will be used to identify the widget in the code, a title that will be used as the widget mark and an icon are all required for each widget. There are also advanced configurations such as widget controls, which are actually fields where the user selects his custom data, and the render script, which produces the final output based on the user data from the widget controls.
Widget Structure
Custom Elementor widget extends the Widget_Base class and it would look something like this:
<?php
use Elementor\Controls_Manager;
use Elementor\Group_Control_Background;
use Elementor\Plugin;
use Elementor\Widget_Base;
if ( ! defined( 'ABSPATH' ) ) {
// Exit if accessed directly.
exit;
}
class PE_Carousel_Widget extends Widget_Base {
/**
* Get the widget's name.
*
* @return string
*/
public function get_name(): string {
return 'pe-carousel-widget';
}
/**
* Get the widget's title.
*
* @return string
*/
public function get_title(): string {
return esc_html__( 'PE Carousel', PE_PLUGIN_DOMAIN );
}
/**
* Get the widget's icon.
*
* @return string
*/
public function get_icon(): string {
return 'fa fa-clipboard';
}
/**
* Add the widget to a category.
* Previously setup in the class-widgets.php file.
*
* @return string[]
*/
public function get_categories(): array {
return [ 'pe-category' ];
}
protected function _register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => esc_html__( 'Carousel', PE_PLUGIN_DOMAIN ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'background',
'label' => __( 'Background', PE_PLUGIN_DOMAIN ),
'types' => [ 'classic', 'gradient', 'video' ],
'selector' => '{{WRAPPER}} .pe-wrapper-carousel',
]
);
$this->end_controls_section();
}
protected function render() {
if (Plugin::$instance->editor->is_edit_mode()) {
// If the Elementor editor is opened.
}
}
}
Plugin::instance()->widgets_manager->register_widget_type( new PE_Carousel_Widget() );
Let’s take a look at how it works:
get_name()
– return a widget nameget_title()
– return the widget title that will be used as the name for the widgetget_icon()
– optional but recommended since it helps you to modify the widget iconget_categories
– return the category name as a string_register_controls
– lets you define which setting fields your widget is going to haverender()
– render the code and generate the HTML
There are several other methods in the Widget_Base class that you can use to do various things, but for now, this should suffice.
Carousel Elementor Widget
To tie it together, we’ll make an Elementor widget that will show a carousel of a custom post type (let’s call it ‘testimonial’).
Widget Controls
We need to add the widget controls using the _register_controls() method, in this case, we are going to need several controls. You can find the full list of available controls here.
- background
- posts per page
- order by
- order type (ASC or DESC)
All of the controls can be wrapped into a section like this:
// All of the controls can be wrapped into a section.
$this->start_controls_section(
'content_section',
[
'label' => esc_html__( 'Carousel', PE_PLUGIN_DOMAIN ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
// add your controls here
$this->end_controls_section();
Now, let’s add out contorls:
$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'background',
'label' => __( 'Background', PE_PLUGIN_DOMAIN ),
'types' => [ 'classic', 'gradient', 'video' ],
'selector' => '{{WRAPPER}} .pe-wrapper-carousel',
]
);
$this->add_control(
'pe-testimonials-posts-per-page',
[
'label' => __( 'Post Per Page', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => '5',
'options' => [
'5' => '5',
'10' => '10',
'-1' => '-1',
]
]
);
$this->add_control(
'pe-testimonials-order-by',
[
'label' => __( 'Order By', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => 'rand',
'options' => [
'name' => 'name',
'title' => 'title',
'date' => 'date',
'rand' => 'rand'
]
]
);
$this->add_control(
'pe-testimonials-order',
[
'label' => __( 'Order', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => 'DESC',
'options' => [
'ASC' => 'ASC',
'DESC' => 'DESC',
]
]
);
If you did everything right, your widget should look like the image below:
Note: The widget class should only be included if Elementor is active and loaded.
Frontend Rendering
Finally, we need to implement our render() method, which will get the control options and output the testimonials.
<?php
use Elementor\Controls_Manager;
use Elementor\Group_Control_Background;
use Elementor\Plugin;
use Elementor\Widget_Base;
if ( ! defined( 'ABSPATH' ) ) {
// Exit if accessed directly.
exit;
}
class PE_Carousel_Widget extends Widget_Base {
/**
* Get the widget's name.
*
* @return string
*/
public function get_name(): string {
return 'pe-carousel-widget';
}
/**
* Get the widget's title.
*
* @return string
*/
public function get_title(): string {
return esc_html__( 'PE Carousel', PE_PLUGIN_DOMAIN );
}
/**
* Get the widget's icon.
*
* @return string
*/
public function get_icon(): string {
return 'fa fa-clipboard';
}
/**
* Add the widget to a category.
* Previously setup in the class-widgets.php file.
*
* @return string[]
*/
public function get_categories(): array {
return [ 'pe-category' ];
}
protected function _register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => esc_html__( 'Carousel', PE_PLUGIN_DOMAIN ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'background',
'label' => __( 'Background', PE_PLUGIN_DOMAIN ),
'types' => [ 'classic', 'gradient', 'video' ],
'selector' => '{{WRAPPER}} .pe-wrapper-carousel',
]
);
$this->add_control(
'pe-testimonials-posts-per-page',
[
'label' => __( 'Post Per Page', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => '5',
'options' => [
'5' => '5',
'10' => '10',
'-1' => '-1',
]
]
);
$this->add_control(
'pe-testimonials-order-by',
[
'label' => __( 'Order By', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => 'rand',
'options' => [
'name' => 'name',
'title' => 'title',
'date' => 'date',
'rand' => 'rand'
]
]
);
$this->add_control(
'pe-testimonials-order',
[
'label' => __( 'Order', PE_PLUGIN_DOMAIN ),
'type' => Controls_Manager::SELECT,
'multiple' => false,
'default' => 'DESC',
'options' => [
'ASC' => 'ASC',
'DESC' => 'DESC',
]
]
);
$this->end_controls_section();
}
protected function render() {
$postsPerPage = $this->get_settings_for_display('pe-testimonials-posts-per-page');
$orderBy = $this->get_settings_for_display('pe-testimonials-order-by');
$order = $this->get_settings_for_display('pe-testimonials-order');
$args = array(
'post_type' => 'testimonial', // or any other custom post type
'post_status' => 'publish',
'posts_per_page' => $postsPerPage,
'orderby' => $orderBy,
'order' => $order
);
$posts = new WP_Query($args);
$testimonials = $posts->posts;
if (Plugin::$instance->editor->is_edit_mode()) {
// If the Elementor editor is opened.
} ?>
<!-- include the background class if yuo want to add a background color -->
<div class="pe-section-posts pe-wrapper-carousel">
<div class="pe-cpt-container">
<?php if($testimonials):
foreach ($testimonials as $testimonial): ?>
<div class="pe-cpt">
<h3><?= $testimonial->post_title; ?></h3>
<p><?= $testimonial->post_content; ?></p>
</div>
<?php endforeach;
endif; ?>
</div>
</div>
<?php }
}
Plugin::instance()->widgets_manager->register_widget_type( new PE_Carousel_Widget() );
Don’t forget to include the slick carousel styles and scripts. They can be found here. Without those, the posts will be shown as a list. You can do your styling if you wish but this is a faster way to create a beautiful carousel.
Final Notes
- The widget class should only be included if Elementor is active and loaded.
- You can find the full list of available widget controls here.