x-bind
x-bind allows you to set HTML attributes on elements based on the result of JavaScript expressions.
For example, here's a component where we will use x-bind to set the placeholder value of an input:
<div x-data="{ placeholder: 'Type here...' }">
<input type="text" x-bind:placeholder="placeholder">
</div>Shorthand syntax
If x-bind: is too verbose for your liking, you can use the shorthand: :.
Here's the same input element as above, but using the shorthand syntax instead:
<input type="text" :placeholder="placeholder">Binding classes
x-bind is most often useful for setting specific classes on an element based on your Alpine state. Here is a simple example, that toggles hidden class based on the open state:
<div x-data="{ open: false }">
<button x-on:click="open = ! open">Toggle Dropdown</button>
<div :class="open ? '' : 'hidden'">
Dropdown Contents...
</div>
</div>Special behavior
x-bind:class behaves differently than other attributes under the hood. Consider the following case:
<div class="opacity-50" :class="hide && 'hidden'">If "class" were any other attribute, the :class binding would overwrite any existing class attribute, causing opacity-50 to be overwritten by either hidden or '' here.
However, Alpine treats class bindings differently. It's smart enough to preserve existing classes on an element. So, the above example will result in following DOM element:
<!-- if hide is true -->
<div class="opacity-50 hidden">
<!-- if hide is false -->
<div class="opacity-50">Shorthand conditionals
If you prefer a less verbose syntax, you can use JavaScript's short-circuit evaluation:
<div :class="show ? '' : 'hidden'">
<!-- Is equivalent to: -->
<div :class="show || 'hidden'"><div :class="closed ? 'hidden' : ''">
<!-- Is equivalent to: -->
<div :class="closed && 'hidden'">Class object syntax
Alpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:
<div :class="{ 'hidden': ! show }">This technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's class attribute.
For example, if you wanted to apply the "hidden" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:
<div class="hidden" :class="{ 'hidden': ! show }">Binding styles
Similar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding style attributes.
<div :style="{ color: 'red', display: 'flex' }">
<!-- Will render: -->
<div style="color: red; display: flex;" ...>Conditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.
<div x-bind:style="true && { color: 'red' }">
<!-- Will render: -->
<div style="color: red;">One advantage of this approach is being able to mix it in with existing styles on an element:
<div style="padding: 1rem;" :style="{ color: 'red', display: 'flex' }">
<!-- Will render: -->
<div style="padding: 1rem; color: red; display: flex;" ...>And like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:
<div x-data="{ styles: { color: 'red', display: 'flex' }}">
<div :style="styles">
</div>
<!-- Will render: -->
<div ...>
<div style="color: red; display: flex;" ...>
</div>Binding Alpine Directives Directly
x-bind allows you to bind an object of different directives and attributes to an element. The object keys can be not only the HTML attributes, but also Alpine directives and modifiers. The object values are either plain strings, or in the case of dynamic Alpine directives, callbacks to be evaluated by Alpine.
<div x-data="dropdown()">
<button x-bind="trigger">Open Dropdown</button>
<span x-bind="dialogue">Dropdown Contents</span>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('dropdown', () => ({
open: false,
trigger: {
['x-ref']: 'trigger',
['@click']() {
this.open = true
},
},
dialogue: {
['x-show']() {
return this.open
},
['@click.outside']() {
this.open = false
},
},
}))
})
</script>NOTE
One caveat with this usage of x-bind is that in case of x-for directive, you should return a normal expression string from the callback. For example: ['x-for']() { return 'item in items' }
You can also use this to attach an x-on directive to preserve the case of custom events. This is similar to what the .camel modifier of x-on directive does.
