HTL Tutorial #12: data-sly-unwrap - Rimuovere Wrapper HTML
HTL Tutorial #12: data-sly-unwrap - Rimuovere Wrapper HTML
Cos'è data-sly-unwrap?
data-sly-unwrap rimuove l'elemento HTML ma mantiene il suo contenuto.
Utile per eliminare wrapper non necessari nell'output finale.
Sintassi
<elemento data-sly-unwrap>
Contenuto mantenuto
</elemento>Output:
Contenuto mantenutoL'elemento <elemento> viene rimosso!
Esempio Base
<div data-sly-unwrap>
<p>Questo paragrafo rimane</p>
</div>Output:
<p>Questo paragrafo rimane</p>Il <div> è stato rimosso, il <p> rimane.
Perché Usarlo?
1. Wrapper Tecnici in Edit Mode
In AEM, i componenti hanno spesso wrapper per l'authoring che non servono in publish:
<div data-sly-unwrap="${wcmmode.disabled}">
<p>${properties.text}</p>
</div>In Edit Mode (wcmmode.disabled = false):
<div>
<p>Testo del componente</p>
</div>In Publish Mode (wcmmode.disabled = true):
<p>Testo del componente</p>Il wrapper <div> viene rimosso in publish!
2. Markup Pulito
Evita <div> inutili nel DOM:
<!-- Componente -->
<div data-sly-unwrap="${!properties.showContainer}">
<h2>${properties.title}</h2>
<p>${properties.content}</p>
</div>Se showContainer = false:
<h2>Titolo</h2>
<p>Contenuto</p>Se showContainer = true:
<div>
<h2>Titolo</h2>
<p>Contenuto</p>
</div>3. Conditional Wrapper
<div data-sly-unwrap="${!properties.addWrapper}"
class="card">
<h3>${properties.title}</h3>
<p>${properties.text}</p>
</div>L'autore decide se aggiungere il wrapper .card o no!
data-sly-unwrap Condizionale
data-sly-unwrap accetta un'espressione booleana:
<elemento data-sly-unwrap="${condizione}">
Contenuto
</elemento>- true: Rimuove elemento
- false: Mantiene elemento
Esempio con WCM Mode
<!-- Wrapper solo in edit mode -->
<sly data-sly-unwrap="${wcmmode.disabled}">
<div class="component-wrapper">
<div data-sly-resource="${'parsys' @ resourceType='wcm/foundation/components/parsys'}"></div>
</div>
</sly>Pattern Comuni
1. Lista Condizionale
<ul data-sly-unwrap="${properties.inline}">
<li data-sly-list.item="${properties.items}">
${item}
</li>
</ul>Se inline = false (lista normale):
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>Se inline = true (lista inline, senza <ul>):
<li>Item 1</li>
<li>Item 2</li>2. Wrapper Solo per Multipli Elementi
<div data-sly-unwrap="${itemList.count <= 1}">
<div data-sly-list.item="${properties.items}">
${item}
</div>
</div>1 elemento (unwrap):
<div>Singolo item</div>Multipli elementi (mantiene wrapper):
<div>
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>3. Semantic HTML Condizionale
<section data-sly-unwrap="${!properties.isSection}">
<h2>${properties.title}</h2>
<p>${properties.content}</p>
</section>L'autore decide se usare <section> semantico o solo contenuto.
Element <sly>
HTL fornisce un elemento speciale <sly> che è sempre unwrapped automaticamente:
<sly>
<p>Contenuto</p>
</sly>Output:
<p>Contenuto</p><sly> è perfetto per:
- Template definitions
- Logica HTL senza output
<!-- Template senza wrapper -->
<sly data-sly-template.myTemplate="${@ text}">
<p>${text}</p>
</sly>
<!-- Lista senza wrapper -->
<sly data-sly-list.item="${items}">
<div>${item}</div>
</sly>Differenza <sly> vs data-sly-unwrap
| Feature | <sly> |
data-sly-unwrap |
|---|---|---|
| Unwrap | Sempre | Condizionale |
| Uso | Wrapper logico | Wrapper condizionale |
| Espressione | No | Sì (true/false) |
| Attributi | Non nell'output | Rimossi con elemento |
<!-- SEMPRE rimosso -->
<sly>
Contenuto
</sly>
<!-- CONDIZIONALMENTE rimosso -->
<div data-sly-unwrap="${condition}">
Contenuto
</div>Esempio Completo: Card Component
<div data-sly-use.card="com.example.CardModel"
data-sly-unwrap="${card.unwrapContainer}"
class="card ${card.styleClass}">
<!-- Header condizionale -->
<div data-sly-unwrap="${!card.hasHeader}" class="card-header">
<h3>${card.title}</h3>
</div>
<!-- Body -->
<div class="card-body">
<p>${card.content}</p>
</div>
<!-- Footer condizionale -->
<div data-sly-unwrap="${!card.hasFooter}" class="card-footer">
<a href="${card.linkUrl}">${card.linkText}</a>
</div>
</div>Model:
public class CardModel {
@ValueMapValue
private String title;
@ValueMapValue
private String content;
@ValueMapValue
private String linkUrl;
@ValueMapValue
private String linkText;
@ValueMapValue
private boolean removeContainer;
@ValueMapValue
private String styleClass;
public boolean getHasHeader() {
return title != null && !title.isEmpty();
}
public boolean getHasFooter() {
return linkUrl != null && !linkUrl.isEmpty();
}
public boolean getUnwrapContainer() {
return removeContainer;
}
// Altri getters...
}Output (con container, senza footer):
<div class="card featured">
<div class="card-header">
<h3>Titolo Card</h3>
</div>
<div class="card-body">
<p>Contenuto della card</p>
</div>
</div>Output (senza container, con footer):
<div class="card-header">
<h3>Titolo Card</h3>
</div>
<div class="card-body">
<p>Contenuto della card</p>
</div>
<div class="card-footer">
<a href="/link">Leggi di più</a>
</div>Best Practice
- Usa
<sly>per wrapper sempre rimossi data-sly-unwrapper condizioni: wrapper dinamici- Naming chiaro: variabili come
unwrapContainer,removeWrapper - Semantic HTML: Mantieni markup semantico quando possibile
- Accessibilità: Non rimuovere elementi necessari per screen readers
- Testing: Testa entrambi i casi (wrapped/unwrapped)
Combinazione con Altri Statement
Con data-sly-test
<!-- Mostra solo se c'è contenuto, senza wrapper -->
<div data-sly-test="${properties.content}"
data-sly-unwrap>
${properties.content}
</div>Con data-sly-list
<div data-sly-unwrap="${properties.removeWrapper}">
<div data-sly-list.item="${properties.items}">
${item}
</div>
</div>Con data-sly-element
<!-- Cambia tag O rimuovi completamente -->
<div data-sly-element="${properties.tag}"
data-sly-unwrap="${!properties.tag}">
Contenuto
</div>Errori Comuni
❌ Unwrap con attributi necessari
<!-- SBAGLIATO - perde l'id! -->
<div id="important" data-sly-unwrap>
Contenuto
</div>
<!-- CORRETTO - unwrap solo se id non serve -->
<div id="${properties.id}"
data-sly-unwrap="${!properties.id}">
Contenuto
</div>❌ Dimenticare condizione
<!-- Sempre unwrapped (come <sly>) -->
<div data-sly-unwrap>
<!-- Condizionale -->
<div data-sly-unwrap="${condition}">Esercizi Pratici
- Conditional Container: Componente con wrapper opzionale
- Edit/Publish Mode: Wrapper solo in edit
- List Wrapper: Lista con
<ul>condizionale - Semantic Sections: Section tag opzionale
Prossima Lezione
Nella prossima lezione vedremo data-sly-include e data-sly-resource per includere altri template e componenti.
Lezione #12 della serie HTL Tutorial. ← Lezione precedente | Lezione successiva →