What I'm trying to accomplish
I'm trying to create some custom widgets for Elementor within there WordPress theme. Ive made a custom thumbnail and currently working on creating a thumbnail group:
The thumbnail works (don't mind the [object Object], it should display an font awesome icon):
My problem is as follows. My thumbnail group widget has a button to add a new thumbnail to itself:
The problem
I cant seem to get this button to work properly and since i have limited PHP experience i don't know if its even possible. See the thumbnail class is a PHP class (back-end language) and I'm trying to create a new instance in the front end. I have no clue on how to tackle this issue.
The other reason id like to solve this issue is because it will make life a LOT easier in the future if i want to create dynamic widgets.
Looking for suggestions
Id like some suggestions on how to solve this, I'm thinking about:
- re implementing the "add new thumbnail" button in JavaScript (would like some help on where to start from there if that's the way to go)
- make a static thumbnail group that only has 4 thumbnails (this is a last resort)
- just paste 4 thumbnails next to each other manually (I'm not gonna settle for this)
The code I use to make the widgets work can be found bellow (feel free to use it if you like it). Thanks in advance!
To reproduce
Bellow is the folder structure that is required to reproduce my situation 1 on 1:
Register custom widgets
This is the "custom-elementor.php" file which loops trough the custom widgets folder and registers every widget within that folder:
<?php
namespace NameSpaceExample;
// Global directory variables
$elementorDir = dirname( __FILE__ ) . 'elementor\';
$widgetsDir = $elementorDir . 'custom-widgets\';
str_replace("\", "/", $elementorDir);
str_replace("\", "/", $widgetsDir);
// use ElementorPlugin; ?????
class Widget_Loader {
// Make class static
private static $_instance = null;
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function include_and_register_widgets(){
$dir = $GLOBALS['widgetsDir'];
foreach (glob($dir . '*.php') as $file)
{
require_once($file);
$class = 'NameSpaceExampleWidgets\' . basename($file, '.php');
if (class_exists($class))
{
$obj = new $class;
$obj->register_self();
}
}
}
public function __construct(){
add_action('elementor/widgets/widgets_registered', [$this, 'include_and_register_widgets'], 99);
}
}
// Instantiate Plugin Class
Widget_Loader::instance();
Custom thumbnail
This PHP code represents the custom thumbnail widget:
<?php
namespace NameSpaceExampleWidgets;
use ElementorWidget_Base;
use ElementorControls_Manager;
if (!defined('ABSPATH')) exit; // Exit if accessed directly
class Thumbnail extends Widget_Base{
public function get_name(){
return 'thumbnail';
}
public function get_title(){
return 'Thumbnail';
}
public function get_icon(){
return 'fa fa-icons';
}
public function get_categories(){
return ['general'];
}
public function register_self() {
ElementorPlugin::instance()->widgets_manager->register_widget_type(new self());
}
protected function _register_controls(){
$this->start_controls_section(
'section_content',
[
'label' => 'Settings',
]
);
$this->add_control(
'thumbnail_icon',
[
'label' => 'Thumbnail Icon',
'type' => ElementorControls_Manager::ICONS,
'default' => [
'value' => 'fa fa-pencil-ruler',
'library' => 'solid',
],
]
);
$this->add_control(
'thumbnail_heading',
[
'label' => 'Thumbnail Heading',
'type' => ElementorControls_Manager::TEXT,
'default' => 'Example Heading'
]
);
$this->add_control(
'thumbnail_content',
[
'label' => 'Thumbnail Content',
'type' => ElementorControls_Manager::WYSIWYG,
'default' => 'Some example content. Start Editing Here.'
]
);
$this->end_controls_section();
}
protected function render(){
$settings = $this->get_settings_for_display();
$this->add_inline_editing_attributes('thumbnail_heading', 'basic');
$this->add_inline_editing_attributes('thumbnail_content', 'basic');
?>
<article class="col-xs-12 col-sm-6 col-md-3 thumbnail-style thumbnail-icon-item text-center">
<div class="thumbnail">
<div class="thumbnail-icon">
<?php ElementorIcons_Manager::render_icon( $settings['thumbnail_icon'], [ 'aria-hidden' => 'true' ] ); ?>
</div>
<div class="caption">
<div class="thumbnail-heading" <?php echo $this->get_render_attribute_string('thumbnail_heading'); ?>>
<h4>
<?php echo $settings['thumbnail_heading']?>
</h4>
</div>
<div class="thumbnail-content" <?php echo $this->get_render_attribute_string('thumbnail_content'); ?>>
<?php echo $settings['thumbnail_content'] ?>
</div>
</div>
</div>
</article>
<?php
}
protected function _content_template(){
?>
<#
view.addInlineEditingAttributes( 'thumbnail_heading', 'basic' );
view.addInlineEditingAttributes( 'thumbnail_content', 'basic' );
#>
<article class="col-xs-12 col-sm-6 col-md-3 thumbnail-style thumbnail-icon-item text-center">
<div class="thumbnail">
<div class="thumbnail-icon">
<div>
{{{ settings.thumbnail_icon }}}
</div>
</div>
<div class="caption">
<div class="thumbnail-heading">
<h4 {{{ view.getRenderAttributeString( 'thumbnail_heading' ) }}}>
{{{ settings.thumbnail_heading }}}
</h4>
</div>
<div class="thumbnail-content">
<p {{{ view.getRenderAttributeString( 'thumbnail_content' ) }}}>
{{{ settings.thumbnail_content }}}
</p>
</div>
</div>
</div>
</article>
<?php
}
}
Custom thumbnail group
This is the ThumbnailGroup widget code:
<?php
namespace NameSpaceExampleWidgets;
use ElementorWidget_Base;
use ElementorControls_Manager;
if (!defined('ABSPATH')) exit; // Exit if accessed directly
class ThumbnailGroup extends Widget_Base{
public function get_name(){
return 'thumbnail_group';
}
public function get_title(){
return 'Thumbnail Group';
}
public function get_icon(){
return 'fa fa-layer-group';
}
public function get_categories(){
return ['general'];
}
public function register_self() {
ElementorPlugin::instance()->widgets_manager->register_widget_type(new self());
}
protected function _register_controls(){
$this->start_controls_section(
'section_content',
[
'label' => 'Settings',
]
);
$this->add_control(
'new_thumbnail_group_button',
[
'label' => 'New Thumbnail',
'type' => ElementorControls_Manager::BUTTON,
'text' => 'Add Thumbnail',
'event' => 'addNewThumbnail',
]
);
$this->end_controls_section();
}
protected function render(){
$settings = $this->get_settings_for_display();
?>
<div class="thumbnail-group">
<div class="padding-top-50 padding-bottom-50">
<div class="container">
<div class="row">
<?php $this->addNewThumbnail() ?>
</div>
</div>
</div>
</div>
<?php
}
protected function _content_template(){
?>
<#
#>
<div class="thumbnail-group">
<div class="padding-top-50 padding-bottom-50">
<div class="container">
<div class="row">
<?php $this->addNewThumbnail() ?>
</div>
</div>
</div>
</div>
<?php
}