Développer un bloc avec des options
Ce tutoriel s’appuie sur le tutoriel d’Edge Delivery Services et de l’éditeur universel, qui vous guide tout au long du processus d’ajout d’options de bloc à un bloc. En définissant les options de bloc, vous pouvez personnaliser l’aspect et la fonctionnalité d’un bloc et permettre différentes variations en fonction des différents besoins du contenu. Cela permet une plus grande flexibilité et la réutilisation dans le système de conception de votre site.
Dans ce tutoriel, vous allez ajouter des options de bloc au bloc Teaser, ce qui permettra aux personnes chargées de la création de choisir entre deux options d’affichage : Par défaut et Côte à côte. L’option Par défaut affiche l’image au-dessus et derrière le texte, tandis que l’option Côte à côte affiche l’image et le texte côte à côte.
Cas d’utilisation courants
Les cas d’utilisation courants pour l’utilisation des Options de bloc dans le développement d’Edge Delivery Services et de l’éditeur universel incluent, sans s’y limiter :
- Variantes de disposition : basculez facilement entre les dispositions. Par exemple, horizontale/verticale ou grille/liste.
- Variations de style : basculez facilement entre les thèmes ou les traitements visuels. Par exemple, le mode clair ou sombre ou le texte grand ou petit.
- Contrôle de l’affichage du contenu : basculez la visibilité des éléments ou basculez entre les styles de contenu (compact ou détaillé).
Ces options offrent flexibilité et efficacité dans la création de blocs dynamiques et adaptables.
Ce tutoriel présente le cas d’utilisation des variations de mise en page, dans lequel le bloc Teaser peut être affiché selon deux dispositions différentes : Par défaut et Côte à côte.
Modèle de bloc
Pour ajouter des options de bloc au bloc Teaser, ouvrez son fragment JSON à l’adresse /block/teaser/_teaser.json
et ajoutez un nouveau champ à la définition de modèle. Ce champ définit sa propriété name
sur classes
, qui est un champ protégé utilisé par AEM pour stocker les options de bloc, qui sont appliquées au HTML Edge Delivery Services du bloc.
Configurations du champ
Les onglets ci-dessous illustrent différentes manières de configurer les options de bloc dans le modèle de bloc, y compris la sélection unique avec une seule classe CSS, la sélection unique avec plusieurs classes CSS et la sélection multiple avec plusieurs classes CSS. Ce tutoriel met en œuvre l’approche plus simple utilisée dans la sélection avec une seule classe CSS.
Ce tutoriel explique comment utiliser un type d’entrée select
(liste déroulante) pour permettre aux personnes chargées de la création de choisir une option de bloc unique, qui est ensuite appliquée comme une classe CSS unique correspondante.
Modèle de bloc
L’option Par défaut est représentée par une chaîne vide (""
), tandis que l’option Côte à côte utilise "side-by-side"
. Les nom et valeur de l’option ne doivent pas nécessairement être identiques, mais la valeur détermine la ou les classes CSS appliquées au code HTML du bloc. Par exemple, la valeur de l’option Côte à côte peut être layout-10
au lieu de side-by-side
. Cependant, il est préférable d’utiliser des noms à la signification sémantique pour les classes CSS, afin d’assurer la clarté et la cohérence des valeurs d’option.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
code language-none h-4 h-8 h-9-18 |
---|
|
HTML de bloc
Lorsque la personne chargée de la création sélectionne une option, la valeur correspondante est ajoutée en tant que classe CSS au code HTML du bloc :
-
Si l’option Par défaut est sélectionnée :
code language-html <div class="block teaser"> <!-- Block content here --> </div>
-
Si l’option Côte à côte est sélectionnée :
code language-html <div class="block teaser side-by-side"> <!-- Block content here --> </div>
Cela permet d’appliquer un style différent et un JavaScript conditionnel en fonction de l’ouverture choisie.
Cette approche n’est pas utilisée dans ce tutoriel, mais elle illustre une autre méthode et des options de bloc avancées.
Le type d’entrée select
permet aux personnes chargées de la création de choisir une option de bloc unique, qui peut éventuellement être mappée à plusieurs classes CSS. Pour ce faire, répertoriez les classes CSS comme valeurs délimitées par des espaces.
Modèle de bloc
Par exemple, l’option Côte à côte peut prendre en charge les variations dans lesquelles l’image s’affiche à gauche (side-by-side left
) ou à droite (side-by-side right
).
[/blocks/teaser/_teaser.json]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
code language-none h-4 h-8 h-9-21 |
---|
|
HTML de bloc
Lorsque la personne chargée de la création sélectionne une option, la valeur correspondante est appliquée sous la forme d’un ensemble de classes CSS séparées par des espaces dans le code HTML du bloc :
-
Si l’option Par défaut est sélectionnée :
code language-html <div class="block teaser"> <!-- Block content here --> </div>
-
Si l’option Côte à côte avec image sur la gauche est sélectionnée :
code language-html <div class="block teaser side-by-side left"> <!-- Block content here --> </div>
-
Si l’option Côte à côte avec image sur la droite est sélectionnée :
code language-html <div class="block teaser side-by-side right"> <!-- Block content here --> </div>
Cela permet d’appliquer un style différent et un JavaScript conditionnel en fonction de l’option choisie.
Cette approche n’est pas utilisée dans ce tutoriel, mais elle illustre une autre méthode et des options de bloc avancées.
Le type d’entrée "component": "multiselect"
permet à la personne chargée de la création de sélectionner plusieurs options simultanément. Cela permet des permutations complexes de l’aspect du bloc en combinant plusieurs choix de conception.
Modèle de bloc
Par exemple, les options Côte à côte, Image à gauche et Image à droite peuvent prendre en charge des variations où l’image est positionnée à gauche (side-by-side left
) ou à droite (side-by-side right
).
[/blocks/teaser/_teaser.json]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
code language-none h-4 h-6 h-8 h-10-21 |
---|
|
HTML de bloc
Lorsque la personne chargée de la création sélectionne plusieurs options, les valeurs correspondantes sont appliquées en tant que classes CSS séparées par des espaces dans le code HTML du bloc :
-
Si les options Côte à côte et Image à gauche sont sélectionnées :
code language-none h-1 <div class="block teaser side-by-side left"> <!-- Block content here --> </div>
-
Si les options Côte à côte et Image à droite sont sélectionnées :
code language-none h-1 <div class="block teaser side-by-side right"> <!-- Block content here --> </div>
Bien que la sélection multiple offre de la flexibilité, elle ajoute de la complexité à la gestion des permutations de conception. Sans restriction, les sélections en conflit peuvent entraîner des expériences interrompues ou compromettant l’image de marque.
Par exemple :
- Sélectionner les options Image à gauche ou Image à droite sans sélectionner l’option Côte à côte les applique implicitement à l’option Par défaut, qui définit toujours l’image comme arrière-plan. Par conséquent, l’alignement à gauche et à droite n’est pas pertinent.
- Les options Image à gauche et Image à droite sont contradictoires.
- Sélectionner l’option Côte à côte sans les options Image à gauche ou Image à droite peut être considéré comme ambigu, car la position de l’image n’est pas spécifiée.
Pour éviter les problèmes et la confusion de la personne chargée de la création lors de l’utilisation de la sélection multiple, assurez-vous que les options sont bien planifiées et que toutes les permutations sont testées. La sélection multiple fonctionne mieux pour des améliorations simples et sans conflit, comme les options « gras » ou « mise en surbrillance », que pour les choix de modification de la disposition.
Cette approche n’est pas utilisée dans ce tutoriel, mais elle illustre une autre méthode et des options de bloc avancées.
Les options de bloc peuvent être définies par défaut lors de l’ajout d’une nouvelle instance de bloc à une page dans l’éditeur universel. Pour ce faire, définissez la valeur par défaut de la propriété classes
dans la définition du bloc.
Définition du bloc
Dans l’exemple ci-dessous, l’option par défaut est définie sur Côte à côte en attribuant la propriété value
du champ classes
à side-by-side
. L’entrée d’option de bloc correspondante dans le modèle de bloc est facultative.
Vous pouvez également définir plusieurs entrées pour le même bloc, chacune avec un nom et une classe différents. Cela permet à l’éditeur universel d’afficher des entrées de bloc distinctes, chacune préconfigurée avec une option de bloc spécifique. Bien qu’ils apparaissent en tant que blocs distincts dans l’éditeur, la base de code contient un seul bloc dont le rendu est effectué dynamiquement en fonction de l’option sélectionnée.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
code language-none h-12 |
---|
|
Configuration de champ pour ce tutoriel
Dans ce tutoriel, nous utiliserons l’approche Sélection avec une seule classe CSS décrite ci-dessus dans le premier onglet, qui permet deux options de bloc discrètes : Par défaut et Côte à côte.
Dans la définition du modèle au sein du fragment JSON du bloc, ajoutez un seul champ de sélection pour les options de bloc. Ce champ permet aux personnes chargées de la création de choisir entre la disposition par défaut et une disposition côte à côte.
[/blocks/teaser/_teaser.json]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
{
"definitions": [...],
"models": [
{
"id": "teaser",
"fields": [
{
"component": "select",
"name": "classes",
"value": "",
"label": "Teaser options",
"description": "",
"valueType": "string",
"options": [
{
"name": "Default",
"value": ""
},
{
"name": "Side-by-side",
"value": "side-by-side"
}
]
},
{
"component": "reference",
"valueType": "string",
"name": "image",
"label": "Image",
"multi": false
},
{
"component": "text",
"valueType": "string",
"name": "imageAlt",
"label": "Image alt text",
"required": true
},
{
"component": "richtext",
"name": "textContent_text",
"label": "Text",
"valueType": "string",
"required": true
},
{
"component": "aem-content",
"name": "textContent_cta",
"label": "CTA",
"valueType": "string"
},
{
"component": "text",
"name": "textContent_ctaText",
"label": "CTA label",
"valueType": "string"
}
]
}
],
"filters": []
}
Mettre à jour le bloc dans l’éditeur universel
Pour rendre l’entrée des options de bloc mises à jour disponible dans l’éditeur universel, déployez les modifications de code JSON sur GitHub, créez une page, ajoutez et créez le bloc Teaser avec l’option Côte à côte, puis publiez la page à prévisualiser. Une fois publiée, chargez la page dans l’environnement de développement local pour le codage.
Transmettre les modifications à GitHub
Pour que l’entrée des options de bloc mises à jour soit disponible dans l’éditeur universel afin de définir les options de bloc et de développer par rapport à au code HTML résultant, le projet doit être lié et les modifications doivent être transmises à une branche GitHub, dans ce cas, la branche block-options
.
# ~/Code/aem-wknd-eds-ue
# Lint the changes to catch any syntax errors
$ npm run lint
$ git add .
$ git commit -m "Add Teaser block option to JSON file so it is available in Universal Editor"
$ git push origin teaser
Créer une page de test
Dans le service de création AEM, créez une page pour ajouter le bloc Teaser pour le développement. En suivant les conventions du chapitre Créer un bloc du tutoriel de développement d’Edge Delivery Services et de l’éditeur universel, créez une page de test sous une page branches
, en lui donnant le nom de la branche Git sur laquelle vous travaillez, dans ce cas, block-options
.
Créer le bloc
Modifiez la nouvelle page Options de bloc dans l’éditeur universel et ajoutez le bloc Teaser. Veillez à ajouter le paramètre de requête ?ref=block-options
à l’URL pour charger la page à l’aide du code de la branche GitHub block-options
.
La boîte de dialogue de bloc comprend désormais une liste déroulante Options de teaser avec les sélections Par défaut et Côte à côte. Sélectionnez Côte à côte et effectuez la création de contenu restante.
Vous pouvez éventuellement ajouter deux blocs Teaser, l’un défini sur Par défaut et l’autre sur Côte à côte. Cela vous permet de prévisualiser les deux options côte à côte pendant le développement et garantit que l’implémentation de l’option Côte à côte n’affecte pas l’option Par défaut.
Publier en prévisualisation
Une fois le bloc de teaser ajouté à la page, publiez la page à prévisualiser à l’aide du bouton Publier et choisissez de publier sur Prévisualisation dans l’éditeur universel.
HTML de bloc
Pour commencer le développement de blocs, commencez par examiner la structure DOM exposée par la prévisualisation Edge Delivery Services. Le modèle DOM a été amélioré avec JavaScript et stylisé avec CSS, ce qui fournit la base pour créer et personnaliser le bloc.
Vous trouverez ci-dessous le DOM du bloc Teaser, avec l’option de bloc Côte à côte sélectionnée, qui est la cible à mettre en forme à l’aide de JavaScript et CSS.
code language-none h-7 |
---|
|
Pour trouver le DOM à mettre en forme, ouvrez la page avec le bloc dans votre environnement de développement local, sélectionnez le bloc à l’aide des outils de développement de votre navigateur web et inspectez le DOM. Cela vous permettra d’identifier les éléments pertinents à mettre en forme.
CSS de bloc
Modifiez l’élément blocks/teaser/teaser.css
pour ajouter des styles CSS spécifiques pour l’option Côte à côte. Ce fichier contient le CSS par défaut du bloc.
Pour modifier les styles de l’option Côte à côte, ajoutez une nouvelle règle CSS étendue dans le fichier teaser.css
qui cible les blocs de teaser configurés avec la classe side-by-side
.
.block.teaser.side-by-side { ... }
Vous pouvez également utiliser l’imbrication CSS pour une version plus concise :
.block.teaser {
... Default teaser block styles ...
&.side-by-side {
... Side-by-side teaser block styles ...
}
}
Dans la règle &.side-by-side
, ajoutez les propriétés CSS nécessaires pour appliquer un style au bloc lorsque la classe side-by-side
est appliquée.
Une approche courante consiste à réinitialiser les styles par défaut en appliquant all: initial
aux sélecteurs partagés, puis en ajoutant les styles requis pour la variante side-by-side
. Si la plupart des styles sont partagés entre les options, le remplacement de propriétés spécifiques peut s’avérer plus facile. Cependant, si plusieurs sélecteurs doivent être modifiés, la réinitialisation de tous les styles et la réapplication des seuls styles nécessaires peuvent rendre le code plus clair et plus facile à gérer.
[/blocks/teaser/teaser.css]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
/* /blocks/teaser/teaser.css */
/* Scope each selector in the block with `.block.teaser` to avoid accidental conflicts outside the block */
.block.teaser {
animation: teaser-fade-in 1s;
position: relative;
width: 1600px;
max-width: 100vw;
left: 50%;
transform: translateX(-50%);
height: 500px;
overflow: hidden;
/* The teaser image */
.image-wrapper {
position: absolute;
z-index: -1;
inset: 0;
box-sizing: border-box;
overflow: hidden;
.image {
object-fit: cover;
object-position: center;
width: 100%;
height: 100%;
transform: scale(1);
transition: transform 0.6s ease-in-out;
.zoom {
transform: scale(1.1);
}
}
}
/* The teaser text content */
.content {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
background: var(--background-color);
padding: 1.5rem 1.5rem 1rem;
width: 80vw;
max-width: 1200px;
.title {
font-size: var(--heading-font-size-xl);
margin: 0;
}
.title::after {
border-bottom: 0;
}
p {
font-size: var(--body-font-size-s);
margin-bottom: 1rem;
animation: teaser-fade-in .6s;
}
p.terms-and-conditions {
font-size: var(--body-font-size-xs);
color: var(--secondary-color);
padding: .5rem 1rem;
font-style: italic;
border: solid var(--light-color);
border-width: 0 0 0 10px;
}
/* Add underlines to links in the text */
a:hover {
text-decoration: underline;
}
/* Add specific spacing to buttons. These button CSS classes are automatically added by Edge Delivery Services. */
.button-container {
margin: 0;
padding: 0;
.button {
background-color: var(--primary-color);
border-radius: 0;
color: var(--dark-color);
font-size: var(--body-font-size-xs);
font-weight: bold;
padding: 1em 2.5em;
margin: 0;
text-transform: uppercase;
}
}
}
/**
* Add styling for the side-by-side variant
**/
/* This evaluates to .block.teaser.side-by-side */
&.side-by-side {
/* Since this default teaser option doesn't have a style (such as `.default`), we use `all: initial` to reset styles rather than overriding individual styles. */
all: initial;
display: flex;
margin: auto;
max-width: 900px;
.image-wrapper {
all: initial;
flex: 2;
overflow: hidden;
* {
height: 100%;
}
.image {
object-fit: cover;
object-position: center;
width: 100%;
height: 100%;
transform: scale(1);
transition: transform 0.6s ease-in-out;
&.zoom {
/* This option has a different zoom level than the default */
transform: scale(1.5);
}
}
}
.content {
all: initial;
flex: 1;
background-color: var(--light-color);
padding: 3.5em 2em 2em;
font-size: var(--body-font-size-s);
font-family: var(--body-font-family);
text-align: justify;
text-justify: newspaper;
hyphens: auto;
p.terms-and-conditions {
border: solid var(--text-color);
border-width: 0;
padding-left: 0;
text-align: left;
}
}
/* Media query for mobile devices */
@media (width <= 900px) {
flex-direction: column; /* Stack elements vertically on mobile */
}
}
}
/** Animations
Scope the @keyframes to the block (teaser) to avoid accidental conflicts outside the block
Global @keyframes can defines in styles/styles.css and used in this file.
**/
@keyframes teaser-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
JavaScript de bloc
L’identification de la ou des options actives du bloc se fait simplement en vérifiant les classes appliquées à l’élément de bloc. Dans cet exemple, nous devons ajuster l’emplacement d’application des styles .image-wrapper
en fonction de l’option active.
La fonction getOptions
renvoie un tableau de classes appliquées au bloc, à l’exclusion de block
et teaser
(car tous les blocs ont la classe block
, et tous les blocs Teaser ont la classe teaser
). Toutes les classes restantes dans le tableau indiquent les options actives. Si le tableau est vide, l’option par défaut est appliquée.
function getOptions(block) {
// Get the block's classes, excluding 'block' and 'teaser'; anything remaining is a block option.
return [...block.classList].filter((c) => !['block', 'teaser'].includes(c));
}
Cette liste d’options peut être utilisée pour exécuter de manière conditionnelle une logique personnalisée dans le JavaScript du bloc :
if (getOptions(block).includes('side-by-side')) {
/* For side-by-side teaser, add the image-wrapper to a higher-level div to support CSS */
block.querySelector(':scope > div:first-child').classList.add('image-wrapper');
} else if (!getOptions(block)) {
/* For the default option, add the image-wrapper to the picture element to support CSS */
block.querySelector('picture').classList.add('image-wrapper');
}
Le fichier JavaScript complet mis à jour pour le bloc de teaser avec les options Par défaut et Côte à côte est le suivant :
[/blocks/teaser/teaser.js]{class="badge neutral" title="Nom de fichier de l’exemple de code ci-dessous."}
/* /blocks/teaser/teaser.js */
/**
* Block options are applied as classes to the block's DOM element
* alongside the `block` and `<block-name>` classes.
*
* @param {HTMLElement} block represents the block's DOM element/tree
*/
function getOptions(block) {
// Get the block's classes, excluding 'block' and 'teaser'.
return [...block.classList].filter((c) => !['block', 'teaser'].includes(c));
}
/**
* Adds a zoom effect to the image using event listeners.
*
* When the CTA button is hovered over, the image zooms in.
*
* @param {HTMLElement} block represents the block's DOM tree
*/
function addEventListeners(block) {
block.querySelector('.button').addEventListener('mouseover', () => {
block.querySelector('.image').classList.add('zoom');
});
block.querySelector('.button').addEventListener('mouseout', () => {
block.querySelector('.image').classList.remove('zoom');
});
}
/**
* Entry point to the block's JavaScript.
* Must be exported as default and accept a block's DOM element.
* This function is called by the project's style.js, passing the block's element.
*
* @param {HTMLElement} block represents the block's DOM element/tree
*/
export default function decorate(block) {
/* Common treatments for all options */
block.querySelector(':scope > div:last-child').classList.add('content');
block.querySelector('h1,h2,h3,h4,h5,h6').classList.add('title');
block.querySelector('img').classList.add('image');
// Process each paragraph and mark it as text or terms-and-conditions
block.querySelectorAll('p').forEach((p) => {
const innerHTML = p.innerHTML?.trim();
if (innerHTML?.startsWith('Terms and conditions:')) {
p.classList.add('terms-and-conditions');
}
});
/* Conditional treatments for specific options */
if (getOptions(block).includes('side-by-side')) {
/* For side-by-side teaser, add the image-wrapper to a higher-level div to support CSS */
block.querySelector(':scope > div:first-child').classList.add('image-wrapper');
} else if (!getOptions(block)) {
/* For the default option, add the image-wrapper to the picture element to support CSS */
block.querySelector('picture').classList.add('image-wrapper');
}
addEventListeners(block);
}
Aperçu du développement
À mesure que les codes CSS et JavaScript sont ajoutés, l’environnement de développement local de l’interface de ligne de commande d’AEM recharge à chaud les modifications, ce qui permet une visualisation rapide et facile de l’impact du code sur le bloc. Pointez sur le CTA et vérifiez que l’image du teaser effectue un zoom avant et arrière.
Appliquer lint à votre code
Veillez à appliquer lint fréquemment à vos modifications de code pour le garder propre et cohérent. Une application régulière de lint permet de détecter les problèmes tôt, ce qui réduit le temps de développement global. N’oubliez pas que vous ne pouvez pas fusionner votre travail de développement dans la branche main
tant que tous les problèmes de linting ne sont pas résolus.
# ~/Code/aem-wknd-eds-ue
$ npm run lint
Aperçu dans l’éditeur universel
Pour afficher les modifications dans l’éditeur universel d’AEM, ajoutez-les, validez-les et envoyez-les à la branche de référentiel Git utilisée par l’éditeur universel. Cela permet de s’assurer que l’implémentation du bloc ne perturbe pas l’expérience de création.
# ~/Code/aem-wknd-eds-ue
$ git add .
$ git commit -m "CSS and JavaScript implementation for Teaser block option Side-by-side"
# JSON files are compiled automatically and added to the commit via a Husky pre-commit hook
$ git push origin block-options
Désormais, les modifications sont visibles dans l’éditeur universel lors de l’utilisation du paramètre de requête ?ref=block-options
.
Félicitations.
Vous avez maintenant exploré les options de bloc dans Edge Delivery Services et l’éditeur universel, ce qui vous donne les outils nécessaires pour personnaliser et rationaliser l’édition de contenu avec une plus grande flexibilité. Commencez à appliquer ces options dans vos projets pour améliorer l’efficacité et maintenir la cohérence.
Pour découvrir les bonnes pratiques et les techniques avancées, consultez la documentation de l’éditeur universel.