HTL Tutorial #10: data-sly-attribute - Manipolare Attributi HTML

HTL Tutorial #10: data-sly-attribute - Manipolare Attributi HTML

Cos'è data-sly-attribute?

data-sly-attribute permette di manipolare dinamicamente gli attributi HTML: aggiungere, modificare o rimuovere attributi basandosi su condizioni o dati.

Sintassi Base

Singolo Attributo

<div data-sly-attribute.nomeAttributo="${valore}">
  Contenuto
</div>

Multipli Attributi

<div data-sly-attribute="${oggetto}">
  Contenuto
</div>

Esempi Semplici

Aggiungere un Attributo

<!-- Aggiunge data-id dinamicamente -->
<div data-sly-attribute.data-id="${product.id}">
  ${product.name}
</div>

Output:

<div data-id="12345">
  Laptop
</div>

Modificare Attributo Esistente

<!-- Override dell'attributo class -->
<div class="card" data-sly-attribute.class="${'card ' + product.status}">
  Contenuto
</div>

Output (se product.status = 'active'):

<div class="card active">
  Contenuto
</div>

Rimuovere un Attributo

Se il valore è null, false, o stringa vuota, l'attributo viene rimosso:

<div title="Default title"
     data-sly-attribute.title="${properties.customTitle}">
  Hover me
</div>

Se properties.customTitle è null:

<div>
  Hover me
</div>

Se properties.customTitle = 'Custom':

<div title="Custom">
  Hover me
</div>

Attributi Multipli con Oggetto

Puoi passare un oggetto per impostare multipli attributi in una volta:

<div data-sly-use.attrs="com.example.AttributesModel"
     data-sly-attribute="${attrs.htmlAttributes}">
  Contenuto
</div>

Java Model:

@Model(adaptables = Resource.class)
public class AttributesModel {

    public Map<String, String> getHtmlAttributes() {
        Map<String, String> attrs = new HashMap<>();
        attrs.put("data-id", "123");
        attrs.put("data-type", "product");
        attrs.put("role", "article");
        return attrs;
    }
}

Output:

<div data-id="123" data-type="product" role="article">
  Contenuto
</div>

Pattern Comuni

1. Classi CSS Condizionali

<div class="card"
     data-sly-attribute.class="${'card ' +
                                 (product.featured ? 'featured ' : '') +
                                 (product.onSale ? 'on-sale' : '')}">
  ${product.name}
</div>

Output (featured=true, onSale=false):

<div class="card featured">
  Laptop
</div>

2. Attributi Data Dinamici

<div data-sly-use.product="com.example.ProductModel"
     data-sly-attribute.data-product-id="${product.id}"
     data-sly-attribute.data-price="${product.price}"
     data-sly-attribute.data-category="${product.category}">
  ${product.name}
</div>

Output:

<div data-product-id="123" data-price="99.99" data-category="electronics">
  Laptop
</div>

3. ARIA Attributes per Accessibilità

<button data-sly-attribute.aria-expanded="${menu.isOpen}"
        data-sly-attribute.aria-controls="${menu.panelId}">
  Menu
</button>

<div data-sly-attribute.id="${menu.panelId}"
     data-sly-attribute.aria-hidden="${!menu.isOpen}">
  <!-- Menu content -->
</div>

4. Link con Target Condizionale

<a href="${link.url}"
   data-sly-attribute.target="${link.external ? '_blank' : ''}"
   data-sly-attribute.rel="${link.external ? 'noopener noreferrer' : ''}">
  ${link.title}
</a>

Output (link esterno):

<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  Visita esempio
</a>

Output (link interno - attributi rimossi):

<a href="/about">
  Chi siamo
</a>

Combinare con Altri Statement

Con data-sly-test

<div data-sly-test="${properties.customId}"
     data-sly-attribute.id="${properties.customId}">
  <!-- Solo se customId esiste, viene aggiunto l'attributo -->
</div>

Con data-sly-list

<ul data-sly-list.item="${properties.items}">
  <li data-sly-attribute.class="${itemList.first ? 'first' : ''}
                                 ${itemList.last ? 'last' : ''}">
    ${item}
  </li>
</ul>

Attributi Booleani HTML5

Per attributi booleani HTML5 come disabled, checked, readonly:

<!-- ✓ CORRETTO - usa true/false -->
<input type="checkbox"
       data-sly-attribute.checked="${user.subscribed}">

<!-- Se user.subscribed = true -->
<input type="checkbox" checked>

<!-- Se user.subscribed = false -->
<input type="checkbox">
<button data-sly-attribute.disabled="${!product.available}">
  Acquista
</button>

<!-- Se available = false -->
<button disabled>Acquista</button>

<!-- Se available = true -->
<button>Acquista</button>

Esempio Completo: Image Component

<div data-sly-use.image="com.example.ImageModel" class="image-wrapper">
  <img src="${image.src}"
       data-sly-attribute.alt="${image.alt}"
       data-sly-attribute.title="${image.title}"
       data-sly-attribute.width="${image.width}"
       data-sly-attribute.height="${image.height}"
       data-sly-attribute.loading="${imageList.first ? '' : 'lazy'}"
       data-sly-attribute.class="${'responsive-image ' + (image.rounded ? 'rounded' : '')}"
       data-sly-attribute.data-caption="${image.caption}">

  <!-- Caption solo se presente -->
  <p data-sly-test="${image.caption}" class="caption">
    ${image.caption}
  </p>
</div>

Output (con tutti i dati):

<div class="image-wrapper">
  <img src="/content/dam/image.jpg"
       alt="Descrizione immagine"
       title="Titolo immagine"
       width="800"
       height="600"
       loading="lazy"
       class="responsive-image rounded"
       data-caption="Foto scattata nel 2025">

  <p class="caption">Foto scattata nel 2025</p>
</div>

Esempio Completo: Form Input

<div data-sly-use.field="com.example.FormFieldModel">
  <input type="${field.type}"
         name="${field.name}"
         data-sly-attribute.id="${field.id}"
         data-sly-attribute.value="${field.value}"
         data-sly-attribute.placeholder="${field.placeholder}"
         data-sly-attribute.required="${field.required}"
         data-sly-attribute.disabled="${field.disabled}"
         data-sly-attribute.minlength="${field.minLength}"
         data-sly-attribute.maxlength="${field.maxLength}"
         data-sly-attribute.pattern="${field.pattern}"
         data-sly-attribute.aria-label="${field.label}"
         data-sly-attribute.aria-describedby="${field.hasError ? field.errorId : ''}"
         data-sly-attribute.class="${'form-control ' + (field.hasError ? 'is-invalid' : '')}">

  <!-- Error message -->
  <div data-sly-test="${field.hasError}"
       data-sly-attribute.id="${field.errorId}"
       class="invalid-feedback">
    ${field.errorMessage}
  </div>
</div>

Attributi Speciali

href e src - URI Context

HTL applica automaticamente context='uri' a href e src:

<a href="${link.url}">Link</a>
<!-- Automaticamente protetto contro javascript:, data:, etc -->

<!-- Equivalente a: -->
<a data-sly-attribute.href="${link.url @ context='uri'}">Link</a>

style Attribute

<div data-sly-attribute.style="${'background-color: ' + theme.bgColor +
                                  '; color: ' + theme.textColor}">
  Styled content
</div>

Attenzione: Preferisci classi CSS quando possibile!

Best Practice

  1. Rimuovi attributi vuoti: HTL lo fa automaticamente con null/false/""
  2. Context automatico: Non serve specificare @ context='uri' per href/src
  3. Attributi booleani: Usa true/false direttamente
  4. Classi CSS: Preferisci classi CSS a style inline
  5. ARIA attributes: Usa per accessibilità
  6. Data attributes: Perfetti per JavaScript hooks
  7. Oggetti per multipli attributi: Più pulito quando hai tanti attributi

Priorità degli Attributi

Se un attributo è definito sia nell'HTML che con data-sly-attribute, vince data-sly-attribute:

<div class="original"
     data-sly-attribute.class="${'new-class'}">
  Contenuto
</div>

<!-- Output: -->
<div class="new-class">
  Contenuto
</div>

Per preservare e aggiungere:

<div class="original"
     data-sly-attribute.class="${'original ' + additionalClass}">
  Contenuto
</div>

Errori Comuni

❌ Nome attributo errato

<!-- SBAGLIATO - usa data-sly-attribute.nome -->
<div data-sly-attribute="data-id"="${value}">

<!-- CORRETTO -->
<div data-sly-attribute.data-id="${value}">

❌ Dimenticare il punto

<!-- SBAGLIATO - manca il . -->
<div data-sly-attributeclass="${value}">

<!-- CORRETTO -->
<div data-sly-attribute.class="${value}">

❌ Attributi booleani con stringhe

<!-- SBAGLIATO - usa true/false -->
<input data-sly-attribute.disabled="${'disabled'}">

<!-- CORRETTO -->
<input data-sly-attribute.disabled="${true}">

Esercizi Pratici

  1. Card Component: Crea card con attributi dinamici (id, data-*, class)
  2. Link List: Lista di link con target="_blank" solo per esterni
  3. Form Builder: Form con validazione e ARIA attributes
  4. Image Gallery: Gallery con lazy loading e attributi dimensionali

Prossima Lezione

Nella prossima lezione vedremo data-sly-element per cambiare dinamicamente il tag HTML di un elemento.


Lezione #10 della serie HTL Tutorial. ← Lezione precedente | Lezione successiva →