HTL Tutorial #6: data-sly-test - Conditional Rendering
HTL Tutorial #6: data-sly-test - Conditional Rendering
What is data-sly-test?
data-sly-test evaluates an expression and:
- If true: renders the element
- If false: completely removes the element from output
Basic Syntax
<element data-sly-test="${condition}">
This appears only if condition is true
</element>Simple Example
<!-- Show only if title exists -->
<h1 data-sly-test="${properties.title}">
${properties.title}
</h1>If properties.title is empty/null:
<!-- No output - element completely removed! -->If properties.title = "Welcome":
<h1>Welcome</h1>Truthy and Falsy Values
HTL considers falsy (= false):
false(boolean)0or0.0(zero number)""(empty string)[](empty array)null/undefined
Everything else is truthy (= true):
true- Any non-zero number
- Any non-empty string
- Arrays with elements
- Objects
<!-- ❌ Does NOT show (falsy) -->
<div data-sly-test="${false}">No</div>
<div data-sly-test="${0}">No</div>
<div data-sly-test="${''}">No</div>
<div data-sly-test="${[]}">No</div>
<!-- ✓ Shows (truthy) -->
<div data-sly-test="${true}">Yes</div>
<div data-sly-test="${1}">Yes</div>
<div data-sly-test="${'hello'}">Yes</div>
<div data-sly-test="${[1,2,3]}">Yes</div>Conditions with Operators
Comparison Operators
<!-- Equality -->
<div data-sly-test="${user.role == 'admin'}">
Admin Panel
</div>
<!-- Greater/Less than -->
<div data-sly-test="${product.stock < 10}" class="alert-warning">
Only ${product.stock} items left!
</div>
<div data-sly-test="${user.age >= 18}">
Adult content
</div>Logical Operators
<!-- AND: both conditions must be true -->
<div data-sly-test="${user.isLoggedIn && user.isPremium}">
Premium Content
</div>
<!-- OR: at least one must be true -->
<div data-sly-test="${properties.showAlways || wcmmode.edit}">
Visible in edit mode or if showAlways is true
</div>
<!-- NOT: inverts the condition -->
<div data-sly-test="${!user.isLoggedIn}">
<a href="/login">Please log in</a>
</div>IN Operator
<!-- Check if tag present in array -->
<span data-sly-test="${'featured' in properties.tags}" class="badge-featured">
Featured
</span>
<!-- Substring in string -->
<div data-sly-test="${'@gmail.com' in user.email}">
Gmail User
</div>IF / ELSE Pattern
HTL doesn't have a native else construct, but you can simulate it:
Pattern 1: Negation
<!-- IF -->
<div data-sly-test="${user.isLoggedIn}">
<p>Welcome, ${user.name}!</p>
</div>
<!-- ELSE (NOT) -->
<div data-sly-test="${!user.isLoggedIn}">
<p>Please <a href="/login">log in</a></p>
</div>Pattern 2: Variable
<!-- Save test result in variable -->
<div data-sly-test.hasContent="${properties.content}">
${properties.content}
</div>
<!-- Use negated variable for else -->
<div data-sly-test="${!hasContent}">
No content available
</div>Pattern 3: IF / ELSE IF / ELSE
<!-- IF -->
<div data-sly-test="${score >= 90}">
<span class="grade-a">Excellent!</span>
</div>
<!-- ELSE IF -->
<div data-sly-test="${score >= 70 && score < 90}">
<span class="grade-b">Good</span>
</div>
<!-- ELSE IF -->
<div data-sly-test="${score >= 50 && score < 70}">
<span class="grade-c">Sufficient</span>
</div>
<!-- ELSE -->
<div data-sly-test="${score < 50}">
<span class="grade-f">Insufficient</span>
</div>Saving the Result in a Variable
The data-sly-test.varName syntax saves the test result:
<!-- Test AND save in variable -->
<div data-sly-test.isAdmin="${user.role == 'admin'}">
<!-- isAdmin is now available -->
<p>Admin Mode: ${isAdmin}</p>
</div>
<!-- Variable does NOT exist outside the block -->Advanced usage - save non-null object:
<!-- If user exists, save it in variable -->
<div data-sly-test.currentUser="${user}">
<!-- currentUser is available here -->
<h2>${currentUser.name}</h2>
<p>${currentUser.email}</p>
</div>Complete Practical Examples
Example 1: Navigation Menu
<nav data-sly-use.nav="com.example.NavigationModel">
<ul class="menu">
<!-- Show Home only if we're not on home -->
<li data-sly-test="${currentPage.path != '/'}">
<a href="/">Home</a>
</li>
<!-- Menu items from model -->
<li data-sly-list.item="${nav.items}">
<!-- Highlight current page -->
<a href="${item.url}"
class="${currentPage.path == item.url ? 'active' : ''}">
${item.title}
</a>
</li>
<!-- Conditional Login/Logout -->
<li data-sly-test="${!user.isLoggedIn}">
<a href="/login">Login</a>
</li>
<li data-sly-test="${user.isLoggedIn}">
<a href="/logout">Logout (${user.name})</a>
</li>
</ul>
</nav>Example 2: Product Card with Badges
<div class="product" data-sly-use.product="com.example.ProductModel">
<h3>${product.name}</h3>
<!-- "New" badge if published less than 7 days ago -->
<span data-sly-test="${product.daysOld < 7}" class="badge-new">
New!
</span>
<!-- "On Sale" badge -->
<span data-sly-test="${product.hasDiscount}" class="badge-discount">
-${product.discountPercent}%
</span>
<!-- "Out of Stock" badge -->
<div data-sly-test="${product.stock == 0}" class="out-of-stock">
<strong>Out of Stock</strong>
</div>
<!-- Buy button only if available -->
<button data-sly-test="${product.stock > 0}" class="btn-buy">
Add to Cart
</button>
<!-- Low stock alert -->
<div data-sly-test="${product.stock > 0 && product.stock < 5}"
class="alert-warning">
Only ${product.stock} items left!
</div>
</div>Example 3: User Dashboard
<div class="dashboard" data-sly-use.user="com.example.UserModel">
<!-- Save isAdmin in variable -->
<div data-sly-test.isAdmin="${user.role == 'admin'}"></div>
<!-- Header with name -->
<h1>Welcome, ${user.name}</h1>
<!-- General stats -->
<div class="stats">
<div class="stat">
<strong>${user.postCount}</strong>
<span>${user.postCount == 1 ? 'post' : 'posts'}</span>
</div>
</div>
<!-- Admin section -->
<section data-sly-test="${isAdmin}" class="admin-panel">
<h2>Administration Panel</h2>
<!-- admin content -->
</section>
<!-- Moderator section -->
<section data-sly-test="${user.role == 'moderator' || isAdmin}">
<h2>Moderation Tools</h2>
<!-- moderation content -->
</section>
<!-- Message for basic users -->
<div data-sly-test="${user.role == 'user' && !user.isPremium}">
<p>
<a href="/premium">Upgrade to Premium</a> for more features!
</p>
</div>
<!-- Premium badge -->
<div data-sly-test="${user.isPremium}" class="premium-badge">
✨ Premium User
</div>
</div>Example 4: Alert System
<div class="alerts" data-sly-use.system="com.example.SystemModel">
<!-- Error -->
<div data-sly-test="${system.hasErrors}" class="alert alert-danger">
<strong>Error!</strong> ${system.errorMessage}
</div>
<!-- Warning -->
<div data-sly-test="${system.hasWarnings && !system.hasErrors}"
class="alert alert-warning">
<strong>Warning:</strong> ${system.warningMessage}
</div>
<!-- Success -->
<div data-sly-test="${system.hasSuccess && !system.hasErrors && !system.hasWarnings}"
class="alert alert-success">
<strong>Success!</strong> ${system.successMessage}
</div>
<!-- Info (default) -->
<div data-sly-test="${!system.hasErrors && !system.hasWarnings && !system.hasSuccess}"
class="alert alert-info">
All good, no notifications.
</div>
</div>Combination with Other Statements
With data-sly-text
<p data-sly-test="${properties.description}"
data-sly-text="${properties.description}">
Placeholder description
</p>With data-sly-list
<!-- List only if it has elements -->
<ul data-sly-test="${properties.items}"
data-sly-list.item="${properties.items}">
<li>${item}</li>
</ul>With data-sly-attribute
<!-- Conditional attribute -->
<div data-sly-test="${properties.customId}"
data-sly-attribute.id="${properties.customId}">
Content
</div>Best Practices
- Prefer simple evaluations:
${variable}instead of${variable != null} - Use variables for complex conditions:
data-sly-test.varName - ELSE pattern with negation:
${!condition} - Combine with other statements when it makes sense
- Test for existence before accessing: avoid errors
- Leverage truthy/falsy: cleaner code
Common Mistakes
❌ Test on literal string
<!-- WRONG - always true! -->
<div data-sly-test="${'false'}">
This always appears!
</div>❌ Confusing = with ==
<!-- WRONG - assignment not supported -->
<div data-sly-test="${user.role = 'admin'}">
<!-- CORRECT - comparison -->
<div data-sly-test="${user.role == 'admin'}">❌ Accessing variable outside scope
<div data-sly-test.myVar="${something}">
${myVar} <!-- OK -->
</div>
${myVar} <!-- ERROR - out of scope! -->Practical Exercises
- Login Widget: Show login form if not logged in, otherwise user dashboard
- Product Filter: Show products only if price is between min and max
- Access Control: Admin panel visible only for admins, moderators have partial access
Next Lesson
In the next lesson we'll discover data-sly-list and data-sly-repeat for iterating over arrays and collections.
Lesson #6 of the HTL Tutorial series. ← Previous lesson | Next lesson →