Skip to content

Binding lists

Greg Bowler edited this page Feb 15, 2024 · 18 revisions

Repeating content is a common requirement when developing any web application: where an HTML element and its sub-tree repeats for every item of a dataset. It might be to output items of a to-do list, list users of the system, or show search results - all of these examples repeat HTML sub-trees to represent a list of items.

In your source HTML, to indicate that an element should be repeated for each item of a list, add the data-list attribute. Any element that has this attribute will be removed from the document, but the original position in the document will be remembered. Now you can call the bindList or bindListCallback function, passing in a list of data such as an array or other iterable, and for each item in the list the original list element will be cloned and added back into the document. The inserted element will be bound with whatever data is contained within the current iteration.

Note: in all examples in this section, we assume an HTMLDocument object is construced and passed to the DocumentBinder constructor. Learn more about constructing DomTemplate objects.

Simple example

This trivial example shows the basic concept by taking an array of strings that represent the days of the week and binding them to the <ul> element. Note that the <li> has the data-list attribute, along with data-bind:text to indicate that its textContent should be set to the value of each respective array item.

Source HTML:

<h1>Days of the week</h1>

<ul>
	<li data-list data-bind:text>Day</li>
</ul>

PHP:

function example(DocumentBinder $binder):void {
	$days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
	$binder->bindList($days);
}

Output HTML:

<h1>Days of the week</h1>

<ul>
	<li>Monday</li>
	<li>Tuesday</li>
	<li>Wednesday</li>
	<li>Thursday</li>
	<li>Friday</li>
	<li>Saturday</li>
	<li>Sunday</li>
</ul>

Non-trivial example

In the trivial example, we bound an array of strings, but the more likely data structure you will be working with is lists of data, like rows from a database.

We'll still use associative arrays in this example to show some simple example data, as if it's come from a database, but it's important to know that the items within a list can be any type of object - either a simple data transfer object (an object with public properties), or an object with functions that are marked as bindable using Bind or BindGetter PHP Attributes.

Note that there is use of curly braces in this example. To learn how they work, see the section on injection.

Source HTML:

<h1>Top selling items</h1>

<ul>
	<li data-list>
		<a href="/shop/product/{{id}}">
			<img src="/product-image/{{id}}.jpg" alt="{{name}} product image" />
			<span class="name" data-bind:text="name">Product title</span>
			<p><span data-bind:text="currency">$</span><span data-bind:text="price">0.00</span></p>
		</a>
	</li>
</ul>

PHP:

function example(DocumentBinder $binder):void {
// The $productList data structure is hard coded here, but 
// it could be provided from a database.
	$productList = [
		[
			"id" => 67,
			"name" => "Pot Plant",
			"currency" => "£",
			"price" => 8.95
		],
		[
			"id" => 20,
			"name" => "Umbrella",
			"currency" => "£",
			"price" => 11.99
		],
		[
			"id" => 74,
			"name" => "Wellington Boots",
			"currency" => "£",
			"price" => 15.00
		],
	];

	$binder->bindList($productList);
}

Output HTML:

<h1>Top selling items</h1>

<ul>
	<li>
		<a href="/shop/product/67">
			<img src="/product-image/67.jpg" alt="Pot Plant product image" />
			<span class="name">Pot Plant</span>
			<p><span>£</span><span>8.95</span></p>
		</a>
	</li>
	<li>
		<a href="/shop/product/20">
			<img src="/product-image/20.jpg" alt="Umbrella product image" />
			<span class="name">Umbrella</span>
			<p><span>£</span><span>11.99</span></p>
		</a>
	</li>
	<li>
		<a href="/shop/product/74">
			<img src="/product-image/74.jpg" alt="Wellington Boots product image" />
			<span class="name">Wellington Boots</span>
			<p><span>£</span><span>15.00</span></p>
		</a>
	</li>
</ul>

Some more complex applications will have lists of data shown within other lists. Imagine a customer order list: the outer list will display customers, and each customer can have a list of orders, and each order can have a list of products. The way you approach this is up to you - you may want to bind the different lists separately, using separate data structures for each list, but it is possible to bind nested lists in one operation, by marking where the sub-lists appear using the data-bind:list attribute. We will go into more detail on this in the next section.

IteratorAggregate and ArrayIterator objects

// TODO


Next, learn how to bind nested lists.