Projects Engine - WordPress

How to Create a Carousel Custom Widget in Elementor

Creating a custom Elementor widget is similar to creating a native WordPress widget.

Home / Blog / Elementor / How to Create a Carousel Custom Widget in Elementor

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 name
  • get_title() – return the widget title that will be used as the name for the widget
  • get_icon() – optional but recommended since it helps you to modify the widget icon
  • get_categories – return the category name as a string
  • _register_controls – lets you define which setting fields your widget is going to have
  • render() – 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.

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:

How to Create a Carousel Custom Widget in Elementor

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.