Créer des skins personnalisées pour un widget Elementor

Suite à mon article sur la création de widgets personnalisés pour le constructeur de page Elementor, j’aborde aujourd’hui la méthode pour créer des habillages personnalisés (ou « skins » en anglais) pour un widget Elementor.

Un habillage ou « skin » dans Elementor, c’est quoi ?

C’est un moyen de proposer plusieurs apparences, habillages …peaux (skins) pour un même widget.
Par exemple, dans la version Pro d’Elementor, le widget « Publications/Posts » propose trois habillages : « Classique », « Cartes » et « Full Content ».
Dans les trois cas le widget a toujours le même rôle : afficher des publications, ce qui change c’est uniquement son apparence.
Les habillages permettent également d’ajouter des contrôles personnalisés par habillage, mais aussi de modifier les contrôles d’un widget.

Les différentes façons de créer des habillages personnalisés

Il existe deux méthodes :

  • Utiliser une extension, par exemple « Elementor Custom Skin » sur le répertoire officiel. Elle permet de créer des templates de boucle (loop) et de les utiliser comme habillages. Vous serez cependant limité aux widgets de Publications.
  • Développer son extension, et c’est le sujet de cet article

Anatomie d’un widget

Avant d’entrer dans le vif du sujet, il me semble important de rappeler comment est construit un widget Elementor :

C’est une classe, écrite en PHP, qui étend une autre classe d’Elementor : Widget_Base.
Dans cette classe on retrouve plusieurs fonctions, certaines sont indispensables comme :
get_name, get_title, register_controls, et… render
Attardons-nous sur cette dernière, la fonction render, qui est responsable de l’affichage du widget. Si les skins d’un widget permettent de contrôler son affichage, alors la fonction render du widget n’est pas utilisée.
Et en effet, lorsqu’on regarde le code du widget Posts, on se rend compte que la fonction render de la classe Posts_Base est vide, et que la classe Posts n’a pas pas du tout de fonction render. Par contre, on trouve une autre fonction : register_skins, qui va charger les trois habillages disponibles pour ce widget : Classic, Cards et Full Content.

En résumé, si un widget dispose d’habillages, alors la fonction render du widget n’est pas obligatoire.

Créer un habillage pour un widget existant

Dans cet article nous allons créer un habillage appelé « Simple » pour le widget Bouton.
Donnons-nous plusieurs objectifs afin d’explorer différentes fonctionnalités :

  1. Ajouter des contrôles pour notre habillage : nous imaginons avoir besoin d’ajouter des attributs HTML personnalisés à notre lien et ajouterons des contrôles pour le faire;
  2. Manipuler les contrôles du widget : nous désactiverons le contrôle « Icône »;
  3. Gérer le rendu de l’habillage : pour l’exemple nous allons alléger le code HTML du widget Bouton natif et afficher nos contrôles crées en #1;

Créer son extension

Tout d’abord il faut créer une extension pour y placer notre habillage. Vous pouvez télécharger l’extension exemple sur mon GitHub et l’installer normalement via le tableau de bord. Une fois activée, vous verrez un nouveau sélecteur d’habillage dans le widget Bouton.
Gardez le code de l’extension sous les yeux tout au long de l’article.

Anatomie de l’extension

  • le dossier /skins contient un dossier par widget, chacun contient un fichier par habillage :
    • /button/skin-simple.php : la classe PHP de notre habillage pour le widget Bouton;
  • elementor-custom-skins.php : le fichier principal de l’extension, je ne m’y attarde pas, il permet de déclarer différentes constantes, charger les traductions, vérifier l’existence d’Elementor, et enfin charger le fichier suivant : plugin.php
  • plugin.php : le fichier qui va charger nos habillages, il contient plusieurs fonctions :
    • include_skins_files : inclut les fichiers d’habillages
    • elementor_init : lance l’inclusion des fichiers d’habillages et les déclare à Elementor sur le hook elementor/widget/{$widget_name}/skins_init, {$widget_name} étant à remplacer par l’identifiant du widget pour lequel nous ajoutons un habillage.
      À l’intérieur de cette fonction, nous utilisons la méthode add_skin de la classe Widget_Base ($widget) pour effectivement ajouter notre habillage au widget. Cette méthode prend en paramètre l’instance de la classe de l’habillage.
    • __construct : ajoute notre fonction elementor_init sur le hook elementor/init, à ce stade les widgets Elementor sont chargés, on peut donc lancer notre propre code.

Créer un habillage

La création d’un habillage se fait via une classe PHP qui étend la classe Skin_Base d’Elementor (située dans elementor/includes/base/skin-base.php). Elle ressemble assez à la création d’un widget, en effet nous retrouvons plusieurs fonctions similaires :

  • get_id : déclare l’identifiant (unique) de notre habillage (skin-simple);
  • get_title : déclare le nom affiché dans l’interface (« Simple »);
  • render : affiche le rendu du widget, elle surpasse la fonction render du widget;

Nous avons également les fonctions add_controls, update_controls, et __construct. Nous les verrons dans cet ordre pour accomplir nos 3 objectifs.

Ajouter des contrôles à un habillage

Imaginons que nous souhaitons ajouter des attributs HTML personnalisés à nos boutons, dont la valeur soit administrable, par exemple pour réaliser du suivi. Le résultat final sera le suivant :
<a href="https://example.com" attribut="test">Cliquez ici</a>
Nous allons proposer un sélecteur qui permet de choisir quel attribut ajouter au lien, et un champ texte pour renseigner la valeur de l’attribut.
Nous avons donc besoin d’ajouter deux nouveaux contrôles, uniquement disponibles pour notre habillage personnalisé : un sélecteur et un champ texte.
Dans le fichier de notre skin (/skins/button/skin-simple.php), nous le faisons dans la fonction add_controls, en commençant par une injection avant le contrôle « Lien » du bouton :

$this->parent->start_injection( [
	'at' => 'before',
	'of' => 'link',
] );

La fonction start_injection permet de cibler précisément où on souhaite ajouter un ou plusieurs contrôles en précisant la position (at) : before ou after, par rapport à un identifiant d’un contrôle existant (of). Ici je déclare que je souhaite commencer mon injection avant le contrôle « Lien » qui a pour identifiant link.

Maintenant que l’injection est commencée, nous pouvons ajouter nos deux contrôles :

$this->add_control(
	'button_custom_attr',
	[
		'label' => __( 'Button attribute', 'elementor-custom-skins' ),
		'type' => Controls_Manager::SELECT,
		'default' => '',
		'options' => [
			'' => __( 'None', 'elementor-custom-skins' ),
			'first-attr' => __( 'First attribute', 'elementor-custom-skins' ),
			'second-attr' => __( 'Second attribute', 'elementor-custom-skins' )
		]
	]
);
$this->add_control(
	'button_custom_attr_value',
	[
		'label' => __( 'Attribute value', 'elementor-custom-skins' ),
		'type' => Controls_Manager::TEXT,
		'default' => '',
	]
);

Le select permet de choisir quel attribut ajouter à notre bouton et le un champ texte permet de saisir la valeur de l’attribut.
Si vous souhaitez en savoir plus sur le fonctionnement des contrôles vous trouverez de la documentation sur le site officiel d’Elementor.

Pour finir, nous terminons notre injection : $this->parent->end_injection();

Notez que nous faisons notre injection sur le parent, c’est à dire le widget bouton ($this->parent), et que nous ajoutons nos contrôles sur l’habillage ($this).

J’utilise pour l’exemple l’injection, mais il est tout à fait possible de créer une ou plusieurs sections (lien vers la documentation).

Vous savez maintenant comment ajouter des contrôles uniquement disponibles pour un habillage, nous verrons plus tard comment les afficher.

Manipuler les contrôles du widget

Vous l’avez vu dans la section précédente : depuis un habillage, nous avons accès au widget parent (ici le bouton). Nous avons donc la possibilité de manipuler les contrôles de ce dernier via notre habillage.
Dans la fonction update_controls, nous allons masquer le contrôle qui permet de sélectionner l’icône du bouton en utilisant la fonction d’Elementor update_control :

$this->parent->update_control(
	'selected_icon',
	[
		'condition' => [
			'_skin!' => 'skin-simple',
		],
	]
);

À nouveau, on agit sur le widget parent ($this->parent), et dans la fonction update_control nous ajoutons une condition lui disant de s’afficher uniquement si l’habillage est différent de notre skin « Simple ».
Idem pour les contrôles « Alignement de l’icône » (icon_align) et « Espacement de l’icône » (icon_indent) : ils seront masqués si l’habillage sélectionné n’est pas pas pour identifiant skin-simple.
À noter que la fonction update_control permet de modifier les paramètres de n’importe quel contrôle, y compris en dehors d’un habillage.

Gérer le rendu de l’habillage

Comme on l’a vu précédemment, lorsqu’un widget dispose d’habillages et que l’un d’eux est sélectionné, c’est le rendu de l’habillage qui prend le pas sur le rendu du widget via la fonction render.
Ici pour l’exemple, j’ai simplement copié la fonction render du widget Bouton avec quelques modifications :

  • j’ai remplacé les appels à $this par $this->parent pour tous les réglages puisqu’ils sont situés dans le widget et non dans l’habillage;
  • j’ai supprimé tout ce qui était relatif à l’affichage de l’icône puisque nous avons supprimé ce contrôle;
  • j’ai ajouté l’affichage de notre attribut personnalisé :
// get skin settings values
$button_custom_attr = $this->get_instance_value( 'button_custom_attr' );
$button_custom_attr_value = $this->get_instance_value( 'button_custom_attr_value' );

// add button attributes from skin settings values
if ( ! empty( $button_custom_attr ) && ! empty( $button_custom_attr_value ) ) {
	$this->parent->add_render_attribute( 'button', $button_custom_attr, $button_custom_attr_value );
}

Notez que pour accéder aux valeurs des contrôles d’un habillage on utilise la fonction get_instance_value, contrairement aux widgets pour lesquels on utilise la fonction get_settings.

Si vous souhaitez en apprendre plus sur les méthodes utilisées dans cette fonction, j’aborde le sujet dans mon article sur la création d’un widget.

Toutes seules, nos 3 fonctions n’afficheront rien, il faut utiliser des hooks pour déclarer à Elementor qu’on est en train de s’amuser avec son bouton.
Pour cela, nous nous plaçons dans la fonction __construct qui est lancée à l’initialisation de notre classe, et on utilise un hook d’Elementor bien pratique car il permet de choisir précisément l’endroit où se placer :

elementor/element/{$widget}/{$section_id}/before_section_end

Dans ce hook, deux portions sont dynamiques : « widget« , « section_id« . (lien vers la documentation officielle)
Dans notre cas nous l’utilisons deux fois :
Une première fois pour ajouter nos contrôles (fonction _controls) sur le widget Bouton (qui a pour identifiant button), dans la section principale (qui a pour identifiant section_button), avant la fin de la section (before_section_end).
Une deuxième fois pour mettre à jour nos contrôles après la fin de la section (after_section_end).

Le résultat final dans l’éditeur est le suivant : à gauche le bouton original et à droite avec notre habillage.

Ce n’est pas très impressionnant j’en conviens ;-), mais vous avez maintenant les bases pour créer des habillages pour personnaliser le rendu des widgets natifs d’Elementor.

Pour ma part j’utilise les habillages au quotidien pour mieux gérer les différents affichages de widgets sans créer une interface trop lourde dans l’éditeur : montrer des contrôles uniquement pour tel habillage.
Je les utilise également pour modifier le rendu HTML des widgets d’Elementor qui parfois ne convient pas en terme d’accessibilité, de sémantique, etc.

Créer un habillage pour ses propres widgets

Pour proposer des habillages dans ses propres widgets la logique reste la même que ci-dessus.
Il faut cependant utiliser la fonction _register_skins dans le widget au lieu de l’action sur le widget existant (elementor/widget/{$widget_name}/skins_init), par exemple dans le widget « Publications » d’Elementor Pro :

protected function _register_skins() {
	$this->add_skin( new Skins\Skin_Classic( $this ) );
	$this->add_skin( new Skins\Skin_Cards( $this ) );
	$this->add_skin( new Skins\Skin_Full_Content( $this ) );
}

Crédit photo : Soorelis – Pixabay

Publié par : Marie Comet

Développeuse et intégratrice web indépendante, spécialisée WordPress.

Retrouvez-moi sur :

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Un commentaire sur Créer des skins personnalisées pour un widget Elementor

  • Fredh

    Bonjour,
    Merci pour cet article !
    J’ai essayé de l’utiliser pour le widget Posts mais cela ne semble pas fonctionner. Que faut-il modifier pour l’adapter à ce widget ?
    Merci

ante. dictum commodo lectus odio ultricies Sed consectetur diam dolor