PHP.GT

Bind properties and modifiers

Most data-bind:* attributes set an element attribute or property, but some bind properties and modifier characters add extra behaviour.

Common bind properties

Here are the bind properties we will use most often:

  • text sets textContent
  • html sets innerHTML
  • value sets form values
  • class adds or toggles class names
  • list binds a nested iterable into a contained list template
  • table binds table data into a <table>
  • remove removes an element conditionally
  • any other property name is treated as a normal attribute name

text and html

HTML:

<p data-bind:text="name">Guest</p>
<div data-bind:html="bioHtml">Plain text bio</div>

If we bind name, the element’s text content changes. If we bind bioHtml, the element’s inner HTML changes.

[!IMPORTANT] html inserts HTML, so it should only be used with trusted content to avoid cross-site scripting (XSS). If we’re only using plain text, stick to text.

class

Without a modifier, data-bind:class adds one or more class names.

HTML:

<div class="panel" data-bind:class="extraClass"></div>

If we bind extraClass to featured, the element ends up with class="panel featured".

If the bound value contains multiple class names separated by spaces, each one is added individually.

HTML:

<div class="panel" data-bind:class="stateClasses"></div>

PHP:

$binder->bindKeyValue("stateClasses", "featured compact");

Output HTML:

<div class="panel featured compact"></div>

Arrays of strings are supported here too, so you can pass an array such as ["featured", "compacts"] and DomTemplate will add the class names in the array.

The : token modifier

The colon modifier toggles a token within a token list, most commonly a class name.

HTML:

<li data-bind:class=":isSelected selected"></li>

If isSelected is truthy, selected is added. If it is falsey, selected is removed.

We can also toggle several classes together:

<li data-bind:class=":isSelected selected featured"></li>

If isSelected is truthy, both selected and featured are added. If it is falsey, they are both removed.

If we omit the explicit token name:

<li data-bind:class=":status"></li>

the bound value itself becomes the token. This also works with several class names:

$binder->bindKeyValue("status", "featured compact");

In that case, both featured and compact are toggled together.

The inverse token modifier

If we want to toggle a token when a value is falsey rather than truthy, we can add ! alongside :.

HTML:

<li data-bind:class=":!isVisible hidden"></li>

Here we can read it as: “add hidden when isVisible is not truthy”.

The order of the modifier characters does not matter, so !: works in the same way as :!:

<li data-bind:class="!:isVisible hidden"></li>

The ? boolean modifier

The question mark toggles an attribute based on truthiness.

HTML:

<button data-bind:disabled="?isArchived">Archive</button>

If isArchived is truthy, the button gets disabled. Otherwise, that attribute is removed.

The ?! inverse boolean modifier

HTML:

<button data-bind:disabled="?!isEditable">Save</button>

Here we can read it as: “disable the button when isEditable is not truthy”.

The order does not matter here either, so !? works in the same way as ?!:

<button data-bind:disabled="!?isEditable">Save</button>

Boolean equality checks with =

We can also make the boolean modifier compare against a specific string value.

HTML:

<label>
	<input type="radio" name="size" value="s" data-bind:checked="?size=s" />
	<span>Small</span>
</label>
<label>
	<input type="radio" name="size" value="m" data-bind:checked="?size=m" />
	<span>Medium</span>
</label>
<label>
	<input type="radio" name="size" value="l" data-bind:checked="?size=l" />
	<span>Large</span>
</label>

If size is "m", the middle radio becomes checked.

This is especially handy for radios, tab state, and selected options.

The @ attribute reference modifier

The @ modifier lets us reuse an existing attribute value instead of repeating ourselves.

HTML:

<input name="email" data-bind:value="@name" />

This behaves as though we had written:

<input name="email" data-bind:value="email" />

There is also a shorthand:

<input name="email" data-bind:value="@" />

which means the same thing as @name.

Combining modifiers

Modifiers can be combined in one expression.

HTML:

<input
	name="size"
	value="m"
	data-bind:checked="?@name=@value"
	data-rebind />

Here we are saying:

  • look up the bind key from name
  • compare it with the current element’s value
  • add checked when they match

We can also bundle several modifier expressions for the same property by separating them with semicolons:

<div data-bind:class=":isSelected selected; :isAdmin admin"></div>

data-rebind

By default, once a bind attribute has been used, DomTemplate removes it to prevent any further bind functions from affecting the element again.

If we want the property to remain bindable, add data-rebind.

HTML:

<button data-bind:disabled="?isBusy" data-rebind>Save</button>

This is useful when we bind the same area more than once during one request.

data-bind:remove

remove is a special bind property that removes the element itself rather than mutating one of its attributes.

HTML:

<p>
	<span data-bind:remove="?isDay">It's night-time.</span>
	<span data-bind:remove="?!isDay">It's daytime.</span>
</p>

If isDay is true, the first span disappears. If isDay is false, the second span disappears.

data-bind:list

This property binds a nested iterable into a child list template.

HTML:

<section data-bind:list="orderList">
	<ul>
		<li data-list data-bind:text="id">Order</li>
	</ul>
</section>

When the key orderList is bound, the contained list template is used.

We will cover that properly in the binding lists section.

data-bind:table

This property tells DomTemplate where table-shaped data should go.

HTML:

<table data-bind:table="sales"></table>

We will go through the supported table data shapes in the binding tables section.


Now that the element-level behaviour is clear, move on to binding lists for the part of the library that does the heavy lifting with repeated markup.