Use custom Javascript for a custom Elementor Widget
-
I developed a custom widget for the Elementor plugin. This plugin list the posts of a custom post type with an horizontal carousel created by a library ‘tiny-slider’, and this carousel have option to filter the posts by categories, date or tags. A click on one of this filter make an ajax request to update the query.
The global structure of the site is a Bedrock architecture, with a custom theme use Sage 10. The render of my widget is handled by a Blade template and controller, and the ajax call request is made by Javascript file. The ajax control is handled by a Trait in another plugin.
There is my actual structure and files :
web ├─ app │ ├─ mu-plugins │ │ ├─ elementor-widgets │ │ │ ├─ widgets │ │ │ │ ├─ MyWidget │ │ │ │ │ ├─ js │ │ │ │ │ │ ├─ my-widget.js │ │ │ │ │ ├─ MyWidget.php │ │ │ ├─ elementor-widgets.php ├─ themes │ ├─ my-theme │ │ ├─ app │ │ │ ├─ View │ │ │ │ ├─ Composers │ │ │ │ │ ├─ Widget.php │ │ ├─ resources │ │ │ ├─ views │ │ │ │ ├─ widgets │ │ │ │ │ ├─ widget-view.blade.php
elementor-widgets.php
: Plugin for register my custom widgetsfunction elementor_register_new_widgets($widgets_manager): void { require_once(__DIR__ . '/widgets/MyWidget/MyWidget.php'); $widgets_manager->register(new MyWidget()); } add_action('elementor/widgets/register', 'elementor_register_new_widgets'); function elementor_add_widget_categories($elements_manager): void { $elements_manager->add_category( 'custom', [ 'title' => 'Custom', 'icon' => 'fa fa-plug', ] ); } add_action('elementor/elements/categories_registered', 'elementor_add_widget_categories');
MyWidget.php
: the custom widget declaration.use App\View\Composers\News; use Elementor\Widget_Base; class ElementorNewsCarousel extends Widget_Base { public function __construct($data = [], $args = null) { parent::__construct($data, $args); wp_register_script('my-widget', plugins_url('/js/my-widget.js', __FILE__), ['jquery', 'tiny-slider'], false, true); } // ... some code public function get_script_depends(): array { return ['my-widget']; // I add my custom JS declared in the constructor } // Render the widget view using the Sage theme protected function render(): void { $templateWidget = new Widget(); // the Widget class in the Composers folder echo view('widgets/widget-view', [ 'wp_query' => $templateWidget->getNews(), 'filter_categories' => $templateWidget->getFilterCategories(), 'filter_tags' => $templateWidget->getFilterTags(), 'filter_date' => $templateWidget->getFilterDate(), 'chips_buttons' => $templateWidget->getChipsButtons() ])->render(); } }
my-widget.js
: the JS code use to interact with the widget.import { tns } from 'tiny-slider'; jQuery(window).on('elementor/frontend/init', () => { const $ = jQuery; // Common const body = $('body'); const loadingModal = $('#modal-loading'); // Homepage let homeCarouselNews = $('#home-carousel-news'); const homeFilterCategoriesBtn = $('#news-filter-categories-btn'); const homeFilterCategories = $('#news-filter-category'); const homeFilterCategoriesItems = $('.news-filter-category-list-item'); const homeFilterTagsBtn = $('#news-filter-tags-btn'); const homeFilterTags = $('#news-filter-tag'); const homeFilterTagsItems = $('.news-filter-tag-list-item'); const homeFilterDateBtn = $('#news-filter-date-btn'); const homeFilterDate = $('#news-filter-date'); const homeFilterDateItems = $('.news-filter-date-list-item'); let homeFilterCategoriesList = []; let homeFilterTagsList = []; let homeFilterDateList = []; let sliderHome = tns({ container: '#home-carousel-news', items: 4, gutter: 36, fixedWidth: 280, slideBy: 1, controls: true, prevButton: '#home-carousel-controls-prev', nextButton: '#home-carousel-controls-next', nav: false, autoplay: false, loop: false, touch: true, freezable: true, }); const showOrHideFilterPopup = function (event) { const popup = event.data.element; popup.toggleClass('hidden'); } const hideAllPopUp = function () { $(homeFilterCategories).addClass('hidden'); $(homeFilterTags).addClass('hidden'); $(homeFilterDate).addClass('hidden'); } const updateHomeFilters = function (categoriesList, tagsList, dateList) { hideAllPopUp(); const getParamsStr = window.location.search ? window.location.search : '?' $.ajax({ url: '/wp/wp-admin/admin-ajax.php' + getParamsStr + '&paged=1', type: 'POST', data: { 'action': 'news_filter_homepage', 'categoriesList': categoriesList.toString(), 'tagsList': tagsList.toString(), 'dateList': dateList.toString(), }, }).done(function (response) { sliderHome.destroy(); homeCarouselNews = $('#home-carousel-news'); homeCarouselNews.empty(); homeCarouselNews.append(response); sliderHome = sliderHome.rebuild(); }).fail(function (response) { console.error('updateHomeFilters', 'fail', response); hideLoadingModal(); }); } const updateElementFilter = function (event) { if (!(event.target.tagName === 'LABEL')) { const elementId = $(event.data.element).find('input').val(); const elementList = event.data.list; const elementType = event.data.type; if (!elementList.includes(elementId)) { elementList.push(elementId) } else { const index = elementList.indexOf(elementId); elementList.splice(index, 1); } updateHomeFilters(homeFilterCategoriesList, homeFilterTagsList, homeFilterDateList); } } //// Categories if (homeFilterCategoriesBtn) { homeFilterCategoriesBtn.click({ element: homeFilterCategories, button: homeFilterCategoriesBtn, }, showOrHideFilterPopup) } if (homeFilterCategoriesItems) { homeFilterCategoriesItems.each(function () { $(this).click({ element: $(this), list: homeFilterCategoriesList, type: 'category' }, updateElementFilter); }) } //// Tags if (homeFilterTagsBtn) { homeFilterTagsBtn.click({ element: homeFilterTags, button: homeFilterTagsBtn, }, showOrHideFilterPopup) } if (homeFilterTagsItems) { homeFilterTagsItems.each(function () { $(this).click({ element: $(this), list: homeFilterTagsList, type: 'tag' }, updateElementFilter); }) } //// Date if (homeFilterDateBtn) { homeFilterDateBtn.click({ element: homeFilterDate, button: homeFilterDateBtn, }, showOrHideFilterPopup) } if (homeFilterDateItems) { homeFilterDateItems.each(function () { $(this).click({ element: $(this), list: homeFilterDateList, type: 'date' }, updateElementFilter); }) } });
My code works if I put the JS file in the theme’s folder assets, but the JS file is loaded in all pages. What I want is, like the Elementor’s documentation say, insert the JS directly inside the widget, to only load the JS when the widget is on the page. But with the architecture I wrote here, my JS file seems to be not loaded by the page. My carousel and ajax calls are not working. But, all of the view is correctly rendered. Any idea of why my JS file is not loaded by the widget?
- The topic ‘Use custom Javascript for a custom Elementor Widget’ is closed to new replies.