HTL Tutorial #3: Logical, Comparison and Relational Operators
HTL Tutorial #3: Logical, Comparison and Relational Operators
Logical Operators
Logical AND &&
Both conditions must be true:
<!-- Show only if title AND author exist -->
<div data-sly-test="${properties.title && properties.author}">
<h2>${properties.title}</h2>
<p>di ${properties.author}</p>
</div>Logical OR ||
At least one condition must be true:
<!-- Show the title from properties OR from pageProperties -->
<h1>${properties.title || pageProperties.title}</h1>
<!-- Multiple fallbacks -->
<p>${properties.description || properties.text || 'Nessuna descrizione disponibile'}</p>Practical example: Image with fallback
<!-- Use customImage, otherwise defaultImage, otherwise placeholder -->
<img src="${properties.customImage || properties.defaultImage || '/images/placeholder.jpg'}"
alt="${properties.altText || 'Immagine'}">Logical NOT !
Negates (inverts) a condition:
<!-- Show only if NOT in edit mode -->
<div data-sly-test="${!wcmmode.edit}">
Contenuto visibile solo in preview/publish
</div>
<!-- Show message only if there are NO results -->
<p data-sly-test="${!results}">
Nessun risultato trovato
</p>Operator Combinations
<!-- (A AND B) OR C -->
<div data-sly-test="${(properties.premium && user.subscribed) || user.isAdmin}">
Contenuto premium
</div>
<!-- NOT (A OR B) -->
<div data-sly-test="${!(properties.hidden || properties.draft)}">
Contenuto pubblicato
</div>Comparison Operators
Equality ==
Checks if two values are equal:
<!-- String comparison -->
<div data-sly-test="${properties.status == 'published'}">
<span class="badge">Pubblicato</span>
</div>
<!-- Number comparison -->
<div data-sly-test="${properties.rating == 5}">
⭐⭐⭐⭐⭐
</div>
<!-- Boolean comparison -->
<div data-sly-test="${properties.featured == true}">
<span class="featured-badge">In evidenza</span>
</div>Inequality !=
Checks if two values are different:
<!-- Show only if status is NOT 'draft' -->
<article data-sly-test="${properties.status != 'draft'}">
${properties.content}
</article>
<!-- Hide elements with priority 0 -->
<div data-sly-test="${properties.priority != 0}">
Priorità: ${properties.priority}
</div>Less Than < and Less Than or Equal <=
<!-- Alert for low stock -->
<div data-sly-test="${product.stock < 10}" class="alert-warning">
Solo ${product.stock} pezzi rimasti!
</div>
<!-- Discount for small orders -->
<p data-sly-test="${cart.total <= 50}">
Spedizione gratuita sopra €50
</p>Greater Than > and Greater Than or Equal >=
<!-- Badge for expert users -->
<span data-sly-test="${user.points > 1000}" class="badge-gold">
Utente Gold
</span>
<!-- Content for adults -->
<div data-sly-test="${user.age >= 18}">
Contenuto riservato
</div>Practical example: Rating system
<div class="rating" data-sly-use.product="com.example.ProductModel">
<!-- Eccellente -->
<span data-sly-test="${product.rating >= 4.5}" class="excellent">
⭐⭐⭐⭐⭐ Eccellente
</span>
<!-- Buono -->
<span data-sly-test="${product.rating >= 3.5 && product.rating < 4.5}" class="good">
⭐⭐⭐⭐ Buono
</span>
<!-- Medio -->
<span data-sly-test="${product.rating >= 2.5 && product.rating < 3.5}" class="average">
⭐⭐⭐ Medio
</span>
<!-- Scarso -->
<span data-sly-test="${product.rating < 2.5}" class="poor">
⭐⭐ Da migliorare
</span>
</div>Relational Operator in
The in operator checks membership and supports different use cases:
1. Substring in String
<!-- Check if 'java' is contained in description -->
<div data-sly-test="${'java' in properties.description}">
Questo post parla di Java
</div>
<!-- Case-sensitive! -->
<p data-sly-test="${'@gmail.com' in user.email}">
Utente Gmail
</p>2. Element in Array
<!-- Check if 'htl' is in the tags array -->
<div data-sly-test="${'htl' in properties.tags}">
Tag HTL presente
</div>
<!-- With numbers -->
<div data-sly-test="${5 in properties.allowedValues}">
Valore 5 è permesso
</div>3. Property in Object
<!-- Check if the 'email' property exists -->
<div data-sly-test="${'email' in user}">
<a href="mailto:${user.email}">Contatta</a>
</div>
<!-- Check complex properties -->
<div data-sly-test="${'socialMedia' in properties}">
<!-- Social links disponibili -->
</div>Practical example: Tag Filter
<div class="post-badges" data-sly-use.post="com.example.PostModel">
<!-- Badge se contiene specifici tag -->
<span data-sly-test="${'featured' in post.tags}" class="badge-featured">
In evidenza
</span>
<span data-sly-test="${'tutorial' in post.tags}" class="badge-tutorial">
Tutorial
</span>
<span data-sly-test="${'advanced' in post.tags}" class="badge-advanced">
Avanzato
</span>
</div>Ternary Operator ? :
Inline condition: condition ? valueIfTrue : valueIfFalse
<!-- Conditional CSS class -->
<div class="${properties.featured ? 'featured' : 'normal'}">
Contenuto
</div>
<!-- Dynamic text -->
<p>${user.isLoggedIn ? 'Benvenuto ' + user.name : 'Effettua il login'}</p>
<!-- Number with plural -->
<p>${itemCount == 1 ? '1 elemento' : itemCount + ' elementi'}</p>Practical example: Status Badge
<span class="status-badge ${properties.status == 'active' ? 'badge-success' : 'badge-danger'}">
${properties.status == 'active' ? '✓ Attivo' : '✗ Inattivo'}
</span>Nested ternary (avoid if possible):
<!-- Works but hard to read -->
<p>${score >= 90 ? 'Eccellente' : score >= 70 ? 'Buono' : score >= 50 ? 'Sufficiente' : 'Insufficiente'}</p>
<!-- Better to use separate data-sly-test! -->Operator Precedence
From highest to lowest priority:
!(NOT)<,<=,>,>===,!=,in&&(AND)||(OR)? :(Ternary)
Use parentheses for clarity:
<!-- Without parentheses - might be confusing -->
${a || b && c}
<!-- With parentheses - clear! -->
${a || (b && c)}Complete Example: Permission System
<div data-sly-use.user="com.example.UserModel"
data-sly-use.page="com.example.PageModel">
<!-- Pulsante Edit: solo per admin o autore della pagina -->
<button data-sly-test="${user.isAdmin || user.id == page.authorId}">
Modifica
</button>
<!-- Pulsante Delete: solo admin -->
<button data-sly-test="${user.isAdmin && page.status != 'published'}">
Elimina
</button>
<!-- Badge Premium -->
<div data-sly-test="${'premium' in user.roles && user.subscriptionActive}">
<span class="badge-premium">Premium</span>
</div>
<!-- Messaggio status -->
<p class="${page.published ? 'text-success' : 'text-warning'}">
${page.published ? 'Pagina pubblicata' : 'Bozza non pubblicata'}
</p>
<!-- Contatore con plurale -->
<p>${page.commentCount == 0 ? 'Nessun commento' :
page.commentCount == 1 ? '1 commento' :
page.commentCount + ' commenti'}</p>
</div>Best Practices
- Use parentheses for clarity:
${(a && b) || c}instead of${a && b || c} - Avoid nested ternaries: prefer multiple
data-sly-test - Simplify complex conditions: move them to the Sling Model
- Be careful with case:
'HTL' in textis different from'htl' in text - The
inoperator is powerful: use it for arrays, strings and objects
Practical Exercises
- Login Status: Show "Welcome [name]" if logged in, otherwise "Login"
- Price Filter: Show products only if price is between €10 and €100
- Tag Checker: Check if a post has at least 2 specific tags
Next Lesson
In the next lesson we will discover Context-Aware XSS Protection: how HTL automatically protects your code from security vulnerabilities.
Lesson #3 of the HTL Tutorial series. ← Previous lesson | Next lesson →