Skip to content

Constructing DomTemplate objects

Greg Bowler edited this page Feb 27, 2023 · 3 revisions

DomTemplate is intended to be used as a part of the PHP.Gt/WebEngine, where all objects are pre-initialised for the developer, but this section will explain how to manually construct the different objects that make up the repository, so you can use the features of DomTemplate in any non-WebEngine projects, or just gain a better understanding of the inner workings.

HTMLDocument

A requirement of DomTemplate is the HTMLDocument of PHP.Gt/Dom. DOM is a PHP implementation of the DOM standard, implemented as closely to the specification as possible. It allows for traversing the element trees within a document, which is how DomTemplate achieves its features.

An HTMLDocument is constructed with a string representation of the current page, in HTML form. This can simply be the output of file_get_contents using the HTML file that matches the currently requested page. The HTML content itself can be the HTML of a page that is extending a partial page.

An instance of an HTMLDocument is required when using any part of DomTemplate.

DocumentBinder and other binding classes

DocumentBinder is the primary object of the repository. Under normal circumstances, this is the only binding object that will be exposed to the developer, as it has all the functions that are required for binding data to the DOM: bindValue, bindKeyValue, bindData, bindTable, bindList and bindListCallback.

Internally however, there are separate classes that handle each of the different types of bind operation. These objects can be supplied to the DocumentBinder in the constructor, or omitted to have default instances created. It's useful to supply DocumentBinder with your own instantiated objects if you need to control their behaviour - for instance, this comes into play throughout unit testing the classes.

The objects available to optionally pass in to the DocumentBinder constructor are:

  • ElementBinder
  • PlaceholderBinder
  • TableBinder
  • ListBinder
  • ListElementCollection
  • BindableCache

Object instances in the constructors of the classes used in this repository are always optional, allowing for a default object to be instantiated if not supplied, but if you are constructing any more than one type of object yourself, be sure to pass the same instance of the dependent classes into the constructors you are using.

ElementBinder

The ElementBinder can bind a single key-value pair to a specific Element of the document. In the constructor, instances of the HTMLAttributeBinder, HTMLAttributeCollection, and PlaceholderBinder can optionally be passed.

There is a single function, bind, which will iterate over any children of the provided context Element that have bind attributes, using the HTMLAttributeCollection, setting the bind properties accordingly, using the HTMLAttributeBinder.

Finally, any curly-brace placeholders within the current Element are bound, by using the PlaceholderBinder.

HTMLAttributeBinder

The HTMLAttributeBinder has no dependencies to other classes. The class deals with attributes that begin with data-bind. Its main function, bind, takes a key, value and context Element to bind to.

The context is searched for any bind attributes and the bind properties are set accordingly, taking into account any modifier characters in the attributes' bind keys.

Another function on the HTMLAttributeBinder is expandAttributes, which takes an Element and expands any attributes that use the @ character in their name, which is a modifier character used to reduce repetition in the HTML by using one attribute value as the bind key.

HTMLAttributeCollection

The HTMLAttributeCollection class is a wrapper around the XPathResult functionality of DOM. Its find function returns a collection of Elements that have bind attributes that other areas of the repository are interested in. Using XPath for this is highly efficient.

PlaceholderBinder

The PlaceholderBinder has no dependencies to other classes. It's one job is to be provided with a key, value and context Element, and search for any double curly braces ({{like this}}) within any Attr or Text nodes of the context, and replace any that match the provided key with the provided value.

TableBinder

The TableBinder class is used to bind data structures to HTMLTableElement Elements within the document. It is dependent on ListElementCollection, ElementBinder, HTMLAttributeBinder, HTMLAttributeCollection, and PlaceholderBinder.

The function detectTableDataStructureType takes an array of data, either in list or associative form, and detects which type of compatible data structure is contained within the array, throwing an IncorrectTableDataFormat exception if the data is not compatible.

The main function of the class is bindTableData, which takes the data structure, a context element and an optional bind key, and provides the table binding functionality described in the binding tables section.

ListBinder

The ListBinder class is responsible for managing elements that have the data-list attribute, and cloning them where needed to bind lists of data to the document. It is dependent on ListElementCollection and BindableCache.

The only public function is bindListData, which takes any iterable data, and provides list binding functionality described in the binding lists section.

ListElementCollection

Used by other classes in the repository, ListElementCollection is constructed with a Document object (specifically, the HTMLDocument instance of the current page), and extracts all list elements from the document within its constructor.

The only public function on the class is get, which provides a ListElement representing the original element in the document that has been extracted. List elements are used to bind lists or table rows.

BindableCache

The BindableCache class is an optimisation tool, used to keep a reference of all properties that are "bindable" on different classes. It uses Reflection to do this, which is quite an expensive operation, so the purpose of the class is to only have to reflect on each class once.

It is not dependent on any other areas of the repository.