HTL Tutorial #9: data-sly-template e data-sly-call - Template Riutilizzabili
HTL Tutorial #9: data-sly-template e data-sly-call - Template Riutilizzabili
Cos'è un Template HTL?
Un template è un blocco di markup riutilizzabile che puoi richiamare multiplevvolte con parametri diversi.
Pensa ai template come funzioni in programmazione!
Sintassi
Definire un Template
<sly data-sly-template.nomeTemplate="${@ param1, param2}">
<!-- markup del template -->
${param1}
${param2}
</sly>Richiamare un Template
<sly data-sly-call="${nomeTemplate @ param1='valore1', param2='valore2'}"></sly>Esempio Base
<!-- Definizione template -->
<sly data-sly-template.userCard="${@ name, email}">
<div class="user-card">
<h3>${name}</h3>
<p>${email}</p>
</div>
</sly>
<!-- Uso del template -->
<sly data-sly-call="${userCard @ name='Mario', email='mario@example.com'}"></sly>
<sly data-sly-call="${userCard @ name='Luigi', email='luigi@example.com'}"></sly>Output:
<div class="user-card">
<h3>Mario</h3>
<p>mario@example.com</p>
</div>
<div class="user-card">
<h3>Luigi</h3>
<p>luigi@example.com</p>
</div>Perché Usare Template?
1. DRY (Don't Repeat Yourself)
Senza template (ripetitivo):
<div class="alert alert-success">
<strong>Successo!</strong> Operazione completata
</div>
<div class="alert alert-danger">
<strong>Errore!</strong> Qualcosa è andato storto
</div>
<div class="alert alert-warning">
<strong>Attenzione!</strong> Controlla i dati
</div>Con template (riutilizzabile):
<!-- Definizione -->
<sly data-sly-template.alert="${@ type, title, message}">
<div class="alert alert-${type}">
<strong>${title}</strong> ${message}
</div>
</sly>
<!-- Uso -->
<sly data-sly-call="${alert @ type='success', title='Successo!', message='Operazione completata'}"></sly>
<sly data-sly-call="${alert @ type='danger', title='Errore!', message='Qualcosa è andato storto'}"></sly>
<sly data-sly-call="${alert @ type='warning', title='Attenzione!', message='Controlla i dati'}"></sly>2. Manutenibilità
Modifichi il template una volta, il cambiamento si applica ovunque!
3. Consistenza
Tutti gli usi del template hanno la stessa struttura.
Template con Liste
Puoi combinare template con data-sly-list:
<!-- Template per singolo prodotto -->
<sly data-sly-template.productCard="${@ product}">
<div class="product-card">
<img src="${product.image}" alt="${product.name}">
<h3>${product.name}</h3>
<p class="price">€ ${product.price}</p>
<button>Aggiungi al carrello</button>
</div>
</sly>
<!-- Uso con lista -->
<div data-sly-use.model="com.example.ProductsModel" class="product-grid">
<sly data-sly-list.product="${model.products}"
data-sly-call="${productCard @ product=product}"></sly>
</div>Template Condizionali
<!-- Template per diversi tipi di badge -->
<sly data-sly-template.badge="${@ type, text}">
<span class="badge badge-${type}">
${text}
</span>
</sly>
<!-- Uso condizionale -->
<div data-sly-use.user="com.example.UserModel">
<sly data-sly-test="${user.isPremium}"
data-sly-call="${badge @ type='gold', text='Premium'}"></sly>
<sly data-sly-test="${user.isModerator}"
data-sly-call="${badge @ type='blue', text='Moderatore'}"></sly>
<sly data-sly-test="${user.isAdmin}"
data-sly-call="${badge @ type='red', text='Admin'}"></sly>
</div>Template Annidati
Puoi definire template dentro template:
<!-- Template principale -->
<sly data-sly-template.articleCard="${@ article}">
<!-- Template interno per meta info -->
<sly data-sly-template.metaInfo="${@ date, author}">
<div class="meta">
<time>${date}</time>
<span>•</span>
<span>${author}</span>
</div>
</sly>
<!-- Usa template -->
<article class="card">
<h3>${article.title}</h3>
<p>${article.excerpt}</p>
<sly data-sly-call="${metaInfo @ date=article.date, author=article.author}"></sly>
</article>
</sly>
<!-- Uso -->
<sly data-sly-call="${articleCard @ article=myArticle}"></sly>Template in File Esterni
Puoi definire template in file separati e includerli:
File: /apps/mysite/components/templates/cards.html
<sly data-sly-template.userCard="${@ user}">
<div class="user-card">
<h3>${user.name}</h3>
<p>${user.email}</p>
</div>
</sly>
<sly data-sly-template.productCard="${@ product}">
<div class="product-card">
<h3>${product.name}</h3>
<p>${product.price}</p>
</div>
</sly>Uso nel componente:
<div data-sly-use.templates="/apps/mysite/components/templates/cards.html">
<sly data-sly-call="${templates.userCard @ user=currentUser}"></sly>
<sly data-sly-call="${templates.productCard @ product=featuredProduct}"></sly>
</div>Pattern Comuni
1. Button Component
<sly data-sly-template.button="${@ text, url, style}">
<a href="${url}" class="btn btn-${style || 'primary'}">
${text}
</a>
</sly>
<!-- Uso -->
<sly data-sly-call="${button @ text='Scopri di più', url='/about', style='secondary'}"></sly>
<sly data-sly-call="${button @ text='Contattaci', url='/contact'}"></sly>2. Icon con Testo
<sly data-sly-template.iconText="${@ icon, text}">
<span class="icon-text">
<i class="icon-${icon}"></i>
<span>${text}</span>
</span>
</sly>
<!-- Uso -->
<sly data-sly-call="${iconText @ icon='calendar', text='15 Gen 2025'}"></sly>
<sly data-sly-call="${iconText @ icon='user', text='Mario Rossi'}"></sly>
<sly data-sly-call="${iconText @ icon='tag', text='Tutorial'}"></sly>3. Social Share Buttons
<sly data-sly-template.socialButton="${@ network, url, title}">
<a href="https://${network}.com/share?url=${url}&title=${title}"
class="social-btn social-${network}"
target="_blank"
rel="noopener">
<i class="icon-${network}"></i>
Condividi su ${network}
</a>
</sly>
<!-- Uso -->
<div class="social-share">
<sly data-sly-call="${socialButton @ network='facebook', url=currentPage.path, title=currentPage.title}"></sly>
<sly data-sly-call="${socialButton @ network='twitter', url=currentPage.path, title=currentPage.title}"></sly>
<sly data-sly-call="${socialButton @ network='linkedin', url=currentPage.path, title=currentPage.title}"></sly>
</div>Esempio Completo: Card System
<!-- ============================================
DEFINIZIONE TEMPLATE
============================================ -->
<!-- Template base card -->
<sly data-sly-template.baseCard="${@ title, content, footer}">
<div class="card">
<div class="card-header">
<h3>${title}</h3>
</div>
<div class="card-body">
${content}
</div>
<div data-sly-test="${footer}" class="card-footer">
${footer}
</div>
</div>
</sly>
<!-- Template per card utente -->
<sly data-sly-template.userCard="${@ user}">
<sly data-sly-call="${baseCard @
title=user.name,
content=user.bio,
footer=user.email}">
</sly>
</sly>
<!-- Template per card prodotto -->
<sly data-sly-template.productCard="${@ product}">
<sly data-sly-call="${baseCard @
title=product.name,
content=product.description,
footer='€ ' + product.price}">
</sly>
</sly>
<!-- ============================================
USO TEMPLATE
============================================ -->
<div data-sly-use.model="com.example.DashboardModel">
<!-- Sezione utenti -->
<section>
<h2>Utenti</h2>
<div class="grid">
<sly data-sly-list.user="${model.users}"
data-sly-call="${userCard @ user=user}"></sly>
</div>
</section>
<!-- Sezione prodotti -->
<section>
<h2>Prodotti in Evidenza</h2>
<div class="grid">
<sly data-sly-list.product="${model.products}"
data-sly-call="${productCard @ product=product}"></sly>
</div>
</section>
</div>Parametri Opzionali
Puoi avere parametri opzionali usando l'operatore OR:
<sly data-sly-template.alert="${@ message, type, icon}">
<div class="alert alert-${type || 'info'}">
<i data-sly-test="${icon}" class="icon-${icon}"></i>
${message}
</div>
</sly>
<!-- Con tutti i parametri -->
<sly data-sly-call="${alert @ message='Successo!', type='success', icon='check'}"></sly>
<!-- Con parametri opzionali omessi -->
<sly data-sly-call="${alert @ message='Info generica'}"></sly>
<!-- Usa type='info' e nessun icon -->Best Practice
- Usa
<sly>per template: non aggiunge markup inutile - Nomi descrittivi:
userCard,alertBoxinvece ditemplate1 - Documentazione: commenta i parametri attesi
- File esterni per template condivisi:
/apps/mysite/components/templates/ - Parametri con default: usa
${param || 'default'} - Non esagerare: template troppo complessi sono difficili da manutenere
- Scope limitato: definisci template vicino al loro uso
Template vs Include
| Feature | Template | Include |
|---|---|---|
| Parametri | ✓ Supportati | ❌ No |
| Riutilizzo | ✓ Multipli call | ✓ Include una volta |
| Scope | Locale al file | Nuovo scope |
| Performance | ✓ Leggero | Include file separato |
| Use Case | Pattern ripetuti | Componenti comuni |
Quando usare cosa:
- Template: Pattern ripetuti nello stesso file (cards, buttons, badges)
- Include: Componenti completi (header, footer, navigation)
Errori Comuni
❌ Parametri non dichiarati
<!-- SBAGLIATO - 'name' non dichiarato -->
<sly data-sly-template.user="${@ email}">
${name} <!-- ERRORE! -->
</sly>
<!-- CORRETTO -->
<sly data-sly-template.user="${@ name, email}">
${name}
</sly>❌ Call prima della definizione
<!-- SBAGLIATO - template non ancora definito -->
<sly data-sly-call="${myTemplate}"></sly>
<sly data-sly-template.myTemplate="${@}">
<!-- ... -->
</sly>
<!-- CORRETTO - definisci prima -->
<sly data-sly-template.myTemplate="${@}">
<!-- ... -->
</sly>
<sly data-sly-call="${myTemplate}"></sly>❌ Template troppo complessi
<!-- SBAGLIATO - troppo complesso -->
<sly data-sly-template.megaTemplate="${@ a, b, c, d, e, f, g}">
<!-- 100 righe di codice -->
</sly>
<!-- CORRETTO - dividi in più template -->
<sly data-sly-template.header="${@ title}">...</sly>
<sly data-sly-template.body="${@ content}">...</sly>
<sly data-sly-template.footer="${@ meta}">...</sly>Esercizi Pratici
- Alert System: Template per alert (success, error, warning, info)
- Navigation Menu: Template per menu items con icone e badge
- Table Rows: Template riutilizzabile per righe tabella
- Media Object: Template per oggetti con immagine + testo
Prossima Lezione
Nella prossima lezione vedremo data-sly-attribute per manipolare attributi HTML dinamicamente.
Lezione #9 della serie HTL Tutorial. ← Lezione precedente | Lezione successiva →