Les suggestions de templates dans Drupal 8

Partager cet article :

Ça n'est pas une nouveauté de Drupal 8, toute partie d'une page d'une page est rendue avec un template.

Il existe un paquet de templates de base :

  • html.html.twig qui s'occupe de rendre le doctype, le contenu de la balise <head> et qui ouvre et ferme la balise <body>
  • page.html.twig lui commence là où html.html.twig s'arrête, c'est a dire l'intérieur de la balise body
  • region.html.twig pour le contenu d'une région (header, footer, content... bref les régions définie dans notre theme)
  • node.html.twig pour le contenu d'une node
  • field.html.twig pour un champ défini dans un type de contenu ou une entité
  • block.html.twig pour les blocks...

Si on prend comme exemple le template node.html.twig qui est donc utilisé pour afficher l'ensemble des noeuds (page, article...)

On peut rendre ces templates plus spécifiques, si on veut par exemple un template spécial pour les noeuds de type "article" on peut copier le fichier node.html.twig en node--article.html.twig.

Il existe aussi d'autres suggestions :

  • node--NID.html.twig en substituant NID par l'id du noeud en question
  • node--VIEW_MODE.html.twig pour utiliser un template différent si on affiche le noeud en mode "teaser" ou "full"
  • ...

On peut connaitre facilement les noms de de template possible pour un élément en activant le debug de twig et en regardant le code html de notre page :

Les suggestions de templates dans le code html

Les éléments préfixés par * sont les noms de template possible, celui préfixé par x est celui effectivement utilisé, ce sont les suggestions de template (ou template suggestions). Il en existe un paquet de base qui suffisent dans la plupart des cas, mais on peut aussi vouloir définir un template plus spécifique.

Définir sa propre suggestion de template

Pour drupal 7 on utilisait pour ça le HOOK_preprocess_HOOK, dans drupal 8 un hook spécifique est disponible : HOOK_theme_suggestions_HOOK.

Le premier "HOOK" doit être remplacé par le nom de notre module qui implémente le hook, le second par le nom de l'élément pour lequel on veut ajouter une suggestion.

Si on a un module qui s'appelle "mon_module" et que l'on veut ajouter une suggestion de template pour les noeuds (node) alors on définira la fonction suivante :

function mon_module_theme_suggestions_node(array $variables) {
  //...
}

cette fonction devra retourner un tableau de suggestion "suggestions" contenant les nouvelles possibilités, par exemple :

function mon_module_theme_suggestions_node(array $variables) {
  $suggestions = [];
  $suggestions[] = 'node__montemplate';
  return $suggestions;
}

Note : quand on définit une suggestion de template dans le code il faut bien remplacer les "--" par des "__"

ainsi :

Si on veut un template html spécifique pour le type de contenu :

function monmodule_theme_suggestions_html(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = 'html__' .$node->getType();
  }
  return $suggestions;
}

La même chose pour "page" :

function slides_core_theme_suggestions_page(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = 'page__' .$node->getType();
  }
  return $suggestions;
}

et pour "region" :

function slides_core_theme_suggestions_region(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = $variables['theme_hook_original'].'__'.$variables['elements']['#region'].'__' .$node->getType();
  }
  return $suggestions;
}

note : j'ai ici utilisé la variable $variables['theme_hook_original'] qui contient le prefixe que l'on doit utiliser pour chaque template (ici "region"), la variable $variables['elements']['#region'] contient elle le nom de la région.

Voici les templates disponibles ainsi pour la région "header" quand on visualise un contenu de type "article" :

Évidement il est possible d'ajouter plusieurs suggestions pour un même élément.

 

Commentaires

Bonjour,

J'ai un soucis au niveau de l'affichage d'un template d'une de mes entités custom.

Quand je regarde ce que me renvoie le tableau du hook_theme_suggestions, j'ai bien ma bonne valeur, à savoir 'mon_entite__full' et le mode debug de twig me dit que je peux utiliser le fichier 'mon-entite--full.html.twig'.
J'ai bien créé ce fichier twig, que j'ai placé dans /themes, mais lorsque j'accède à la page, je suis renvoyé sur le contenu de l'entité dans l'administration et mon template n'est pas chargé.

Avez-vous une idée de ce que je fais de mal ?
Merci pour votre réponse,

Bonjour, le template mon-entite--full.html.twig a bien été placé dans le dossier d'un theme activé ?

S'il est à la racine du dossier thème, il ne sera pas pris en compte.

Si vous utilisez un thème de base de drupal, alors il faudra créer un theme "enfant" de celui ci, l'activer et le définir comme thème par défaut.

Oui il a été placé au bon endroit puisque j'arrive à charger le template mon-entite--teaser.twig.html.

Et bien évidemment j'ai mis mon fichier mon-entite--full.html.twig au même endroit que mon-entite--teaser.html.twig.*

Pour le coup c'est vraiment étrange, si pour un même type d'entité le template teaser fonctionnet et pas le template full... À part un problème de cache ? Je ne vois pas.

J'ai bien recréé le cache après avoir fait mes modifications.
Merci quand même pour votre aide.

Ajouter un commentaire