LogoLogo
HomeDiscourseBlogDiscord
  • Introduction
  • Introduction
    • Quick start
    • Aurelia for new developers
    • Hello world
      • Creating your first app
      • Your first component - part 1: the view model
      • Your first component - part 2: the view
      • Running our app
      • Next steps
  • Templates
    • Template Syntax
      • Attribute binding
      • Event binding
      • Text interpolation
      • Template promises
      • Template references
      • Template variables
      • Globals
    • Custom attributes
    • Value converters (pipes)
    • Binding behaviors
    • Form Inputs
    • CSS classes and styling
    • Conditional Rendering
    • List Rendering
    • Lambda Expressions
    • Local templates (inline templates)
    • SVG
  • Components
    • Component basics
    • Component lifecycles
    • Bindable properties
    • Styling components
    • Slotted content
    • Scope and context
    • CustomElement API
    • Template compilation
      • processContent
      • Extending templating syntax
      • Modifying template parsing with AttributePattern
      • Extending binding language
      • Using the template compiler
      • Attribute mapping
  • Getting to know Aurelia
    • Routing
      • @aurelia/router
        • Getting Started
        • Creating Routes
        • Routing Lifecycle
        • Viewports
        • Navigating
        • Route hooks
        • Router animation
        • Route Events
        • Router Tutorial
        • Router Recipes
      • @aurelia/router-lite
        • Getting started
        • Router configuration
        • Configuring routes
        • Viewports
        • Navigating
        • Lifecycle hooks
        • Router hooks
        • Router events
        • Navigation model
        • Current route
        • Transition plan
    • App configuration and startup
    • Enhance
    • Template controllers
    • Understanding synchronous binding
    • Dynamic composition
    • Portalling elements
    • Observation
      • Observing property changes with @observable
      • Effect observation
      • HTML observation
      • Using observerLocator
    • Watching data
    • Dependency injection (DI)
    • App Tasks
    • Task Queue
    • Event Aggregator
  • Developer Guides
    • Animation
    • Testing
      • Overview
      • Testing attributes
      • Testing components
      • Testing value converters
      • Working with the fluent API
      • Stubs, mocks & spies
    • Logging
    • Building plugins
    • Web Components
    • UI virtualization
    • Errors
      • Kernel Errors
      • Template Compiler Errors
      • Dialog Errors
      • Runtime HTML Errors
    • Bundlers
    • Recipes
      • Apollo GraphQL integration
      • Auth0 integration
      • Containerizing Aurelia apps with Docker
      • Cordova/Phonegap integration
      • CSS-in-JS with Emotion
      • DOM style injection
      • Firebase integration
      • Markdown integration
      • Multi root
      • Progress Web Apps (PWA's)
      • Securing an app
      • SignalR integration
      • Strongly-typed templates
      • TailwindCSS integration
      • WebSockets Integration
      • Web Workers Integration
    • Playground
      • Binding & Templating
      • Custom Attributes
        • Binding to Element Size
      • Integration
        • Microsoft FAST
        • Ionic
    • Migrating to Aurelia 2
      • For plugin authors
      • Side-by-side comparison
    • Cheat Sheet
  • Aurelia Packages
    • Validation
      • Validation Tutorial
      • Plugin Configuration
      • Defining & Customizing Rules
      • Architecture
      • Tagging Rules
      • Model Based Validation
      • Validation Controller
      • Validate Binding Behavior
      • Displaying Errors
      • I18n Internationalization
      • Migration Guide & Breaking Changes
    • i18n Internationalization
    • Fetch Client
      • Overview
      • Setup and Configuration
      • Response types
      • Working with forms
      • Intercepting responses & requests
      • Advanced
    • Event Aggregator
    • State
    • Store
      • Configuration and Setup
      • Middleware
    • Dialog
  • Tutorials
    • Building a ChatGPT inspired app
    • Building a realtime cryptocurrency price tracker
    • Building a todo application
    • Building a weather application
    • Building a widget-based dashboard
    • React inside Aurelia
    • Svelte inside Aurelia
    • Synthetic view
    • Vue inside Aurelia
  • Community Contribution
    • Joining the community
    • Code of conduct
    • Contributor guide
    • Building and testing aurelia
    • Writing documentation
    • Translating documentation
Powered by GitBook
On this page
  • Using if.bind
  • Complementing if.bind with else
  • Performance Considerations
  • Employing show.bind
  • Leveraging switch.bind
  • Grouping Cases
  • Fall-Through Behavior
  • Advanced Scenarios with switch.bind
  • Using switch.bind with Static Expressions
  • Conditional Slot Projection with switch.bind
  • Nesting switch.bind
  • Restrictions on case Usage

Was this helpful?

Export as PDF
  1. Templates

Conditional Rendering

Learn about the various methods for conditionally rendering content in Aurelia 2, with detailed explanations and examples.

Conditional rendering in Aurelia 2 is a powerful feature that lets you create dynamic interfaces that respond to your application's state. You can conditionally include or exclude parts of your view using boolean expressions. This guide will walk you through the different techniques provided by Aurelia to manage conditional content.

Using if.bind

The if.bind directive allows you to conditionally add or remove elements from the DOM based on the truthiness of the bound expression.

When the bound value evaluates to false, Aurelia removes the element and its descendants from the DOM. This process includes the destruction of custom elements, detaching of events, and cleanup of any associated resources, which is beneficial for performance and memory management.

Consider an application where you want to display a loading message while data is being fetched:

<div if.bind="isLoading">Loading...</div>

The isLoading variable controls the presence of the div in the DOM. When it's true, the loading message appears; when false, the message is removed.

Complementing if.bind with else

Aurelia enables if/else structures in the view, similar to conditional statements in JavaScript. The else binding must immediately follow an element with if.bind:

<div if.bind="user.isAuthenticated">Welcome back, ${user.name}!</div>
<div else>Please log in.</div>

This snippet displays a welcome message for authenticated users and a login prompt for others.

Caching Behavior: By default, if.bind caches the view and view model of the element it's applied to. While caching can improve performance by reusing elements rather than recreating them, it may lead to unexpected behavior if you're not anticipating this. If state management becomes an issue, you may disable caching with the verbose syntax:

<custom-element if="value.bind: canShowElement; cache: false"></custom-element>

In this code, value.bind is the condition, and cache: false disables caching. Use this feature judiciously, as excessive use can impact performance.

Performance Considerations

Be mindful that if.bind modifies the DOM structure, which can trigger reflow and repaint processes in the browser. For applications with extensive DOM manipulation, this may become a performance bottleneck. Optimize your usage of if.bind by minimizing the frequency and complexity of conditional rendering operations.

Employing show.bind

The show.bind directive offers an alternative approach to conditional rendering. Instead of adding or removing elements from the DOM, it toggles their visibility. This is akin to applying display: none; in CSS—the element remains in the DOM but is not visible to the user.

<div show.bind="isDataLoaded">Data loaded successfully!</div>

Here, isDataLoaded dictates the visibility of the message. When false, the message is hidden; when true, it is shown. All bindings and events remain intact since the element is not removed from the DOM.

Leveraging switch.bind

For more complex conditional rendering cases, such as when dealing with enumerated values, switch.bind is the ideal choice. It offers a clean, semantic way to handle multiple conditions by mimicking the switch statement in JavaScript.

For instance, given an enumeration of order statuses:

Status.ts
enum Status {
  Received   = 'received',
  Processing = 'processing',
  Dispatched = 'dispatched',
  Delivered  = 'delivered',
  Unknown    = 'unknown',
}

Displaying a message based on the order status with if.bind can become unwieldy. Instead, switch.bind offers a concise and clear approach:

order-status.html
<template switch.bind="orderStatus">
  <span case="received">Order received.</span>
  <span case="processing">Processing your order.</span>
  <span case="dispatched">On the way.</span>
  <span case="delivered">Delivered.</span>
  <span default-case>Status unknown.</span>
</template>

This structure allows for a straightforward mapping between the status and the corresponding message. The default-case acts as a catch-all for any status not explicitly handled.

Grouping Cases

You can bind an array of values to a case, thus grouping multiple conditions:

<template switch.bind="orderStatus">
  <span case.bind="['received', 'processing']">Order is being processed.</span>
  <span case="dispatched">On the way.</span>
  <span case="delivered">Delivered.</span>
</template>

This will display "Order is being processed." for both Received and Processing statuses.

Fall-Through Behavior

The switch construct in Aurelia supports fall-through logic similar to JavaScript's switch:

<template switch.bind="orderStatus">
  <span case="received" fall-through.bind="true">Order received.</span>
  <span case="processing">Order is being processed.</span>
  <!-- Other cases -->
</template>

When orderStatus is Received, both the "Order received." and "Order is being processed." messages will be displayed because of the fall-through attribute.

  • By default, fallThrough is false. If you want a case to fall through, you must explicitly set fall-through.bind="true".

  • You can use the shorthand fall-through="true" instead of binding, which will be interpreted as boolean values.

Advanced Scenarios with switch.bind

Aurelia's switch.bind can accommodate various advanced use cases, making it a versatile tool for conditional rendering. Below are examples of such scenarios:

Using switch.bind with Static Expressions

You can use switch.bind with a static expression, while the case.bind attributes feature more dynamic conditions:

<template repeat.for="num of 100">
  <template switch.bind="true">
    <span case.bind="num % 3 === 0 && num % 5 === 0">FizzBuzz</span>
    <span case.bind="num % 3 === 0">Fizz</span>
    <span case.bind="num % 5 === 0">Buzz</span>
  </template>
</template>

This example iterates over numbers 0 to 99 and applies the FizzBuzz logic, displaying "Fizz", "Buzz", or "FizzBuzz" depending on whether the number is divisible by 3, 5, or both.

Conditional Slot Projection with switch.bind

switch.bind can be combined with au-slot to project content into custom elements conditionally:

<template as-custom-element="foo-bar">
  <au-slot name="s1"></au-slot>
</template>

<foo-bar>
  <template au-slot="s1" switch.bind="status">
    <span case="received">Order received.</span>
    <span case="dispatched">On the way.</span>
    <span case="processing">Processing your order.</span>
    <span case="delivered">Delivered.</span>
  </template>
</foo-bar>

In this case, the custom element foo-bar will project different messages based on the status value.

Nesting switch.bind

switch.bind can be nested within itself for complex conditional logic:

<template>
  <let day.bind="2"></let>
  <template switch.bind="status">
    <span case="received">Order received.</span>
    <span case="dispatched">On the way.</span>
    <span case="processing">Processing your order.</span>
    <span case="delivered" switch.bind="day">
      Expected to be delivered
      <template case.bind="1">tomorrow.</template>
      <template case.bind="2">in 2 days.</template>
      <template default-case>in a few days.</template>
    </span>
  </template>
</template>

This example demonstrates how you can use nested switch.bind statements to handle multiple levels of conditional rendering.

Restrictions on case Usage

The case attribute must be used within the context of a switch and should be its direct child. The following are examples of incorrect and unsupported usages:

<!-- Incorrect: `case` outside of `switch` context -->
<span case="foo"></span>

<!-- Incorrect: `case` not a direct child of `switch` -->
<template switch.bind="status">
  <template if.bind="someCondition">
    <span case="delivered">Delivered</span>
  </template>
</template>

These examples will either throw an error or result in unexpected behavior. If you need to support a use case like this, consider reaching out to the Aurelia team.

By exploring these advanced scenarios, you can harness the full potential of switch.bind to address complex conditional rendering needs in your Aurelia applications. Remember to adhere to the guidelines and limitations to ensure proper functionality and maintainability.

PreviousCSS classes and stylingNextList Rendering

Last updated 1 year ago

Was this helpful?