Description: Completely add or remove a block of HTML from the DOM based on a data condition. The HTML must be nested within a <template> tag.
The core of conditional rendering with x-if revolves around the <template> HTML tag and the x-if directive itself. AlpineJS leverages these to efficiently manage parts of your DOM.
<template x-if="condition">...</template>:
This is the fundamental structure.
x-if directive is placed directly on a <template> tag."condition" is a JavaScript expression that evaluates to either true or false. This expression typically relies on data properties defined in your Alpine component.condition is true, AlpineJS takes the content inside the <template> tag and inserts it into the DOM immediately after where the <template> tag was.condition is false, AlpineJS ensures that the content is completely removed from the DOM. The <template> tag itself remains in the DOM as a placeholder, but its content is absent.Content Inside <template>:
The HTML markup you place inside the <template> ... </template> tags is what gets conditionally rendered. This can be a single <div>, a more complex component structure, or even just text nodes.
<!-- Example: Conditionally show a user profile section -->
<div x-data="{ isLoggedIn: true }">
<button @click="isLoggedIn = !isLoggedIn" class="px-4 py-2 bg-blue-500 text-white rounded">Toggle Login</button>
<template x-if="isLoggedIn">
<div class="user-profile mt-4 p-4 border rounded">
<h3 class="text-lg font-semibold">Welcome, User!</h3>
<p>This is your profile information.</p>
</div>
</template>
</div>
In the example above, the div.user-profile and its contents are only present in the DOM when isLoggedIn is true. When isLoggedIn is false, they are completely removed.
Forgetting to wrap x-if content in a <template> tag:
A very common mistake is to put x-if directly on the element you want to show or hide, like <div x-if="condition">...</div>. This will not work as expected for DOM manipulation. AlpineJS's x-if directive is specifically designed to operate on a <template> tag. The <template> acts as an inert container whose content is stamped out or removed based on the condition.
Incorrect (will not work as intended for DOM addition/removal):
<!-- This will NOT conditionally render the div in the DOM by adding/removing it -->
<div x-if="showMessage">Hello, World!</div>
Correct:
<template x-if="showMessage">
<div>Hello, World!</div>
</template>
Confusing x-if with x-show:
Both directives control visibility, but they do it differently:
x-if: Adds or removes elements from the DOM.
x-if when:
x-show: Toggles the CSS display: none; style on the element.
x-show when:
x-show is generally lighter for quick toggles.Think of x-if as constructing or demolishing a part of a building, and x-show as simply opening or closing the door to an existing room.
State within an x-if block is destroyed when hidden:
Because x-if completely removes the HTML elements from the DOM when its condition becomes false, any state associated with those elements is destroyed. This includes:
x-if block (they are re-initialized from scratch when the block is shown again).When the condition becomes true again, Alpine re-creates the elements and re-initializes any Alpine components within that block. If you need to maintain state across visibility changes, x-show is the appropriate directive.
This panel contains potentially complex settings. It's only added to the DOM when you explicitly show it. Notice the behavior of the input field and the nested counter below when this panel is hidden and then shown again.
Parent component's configValue:
This input's value is reset because we explicitly clear configValue in the parent component when hiding the panel.
This counter is part of a nested Alpine component (defined by x-data) within the x-if block. Its state (counter and initTime) is completely reset each time the panel is shown because the component is re-initialized.
Nested Counter:
Initialized at:
Inspect the DOM using your browser's developer tools. You'll see this entire 'Advanced Configuration Panel'
<div> appear and disappear from the DOM tree as you toggle it, not just get a display: none; style.
Advanced configuration is currently hidden. Click the button above to render it into the DOM.