Synthetic view
Learn how you can dynamically synthesize view from templates generated on runtime.
Last updated
Was this helpful?
Learn how you can dynamically synthesize view from templates generated on runtime.
Last updated
Was this helpful?
While you can use the enhance
API to hydrate dynamically (on runtime) generated templates, this tutorial shows some primitives to do the same with more controls to you.
We will write two custom elements. To make it easy to follow the custom elements are intentionally made trivial.
Then we will generate a template that is constructed on runtime using these custom elements.
Finally we will use lower level Aurelia APIs such as ViewFactory
and Controller
to hydrate the template.
You can see a working example .
Before going any further, you should be familiar with some basic Aurelia concepts as well as some fundamental Javascript ones as well. While these are not hard prerequisites, please know that some concepts used in this tutorial out of context might be confusing or difficult to understand.
Creating a new Aurelia app. This won't be covered in this tutorial and you may refer the other tutorials to this end.
You have familiarized yourself with the .
You have familiarized yourself with .
You are familiar with . You don't need to be a master of it, just familiar with its existence and why it matters in Aurelia.
Native Web APIs, such as .
First, let us write some custom elements. These custom elements will be rather simplistic in nature so that we don't get tangled into the logic of complex custom elements too much. To this end we will have two custom elements, namely normal-text
and value-text
. These custom-elements display a bound value
inside a <span>
and a <strong>
element respectively as shown in the following code fragment.
Make sure that you have registered those custom elements.
App
Let us assume that the starting point of our app is as follows.
The idea is to add the dynamically generated and hydrated nodes in the div[ref=containerEl]
using the add
method and remove those using the remove
method.
The process of dynamically adding the hydrated nodes can be broadly divided into the following steps:
Create the DOM fragment under a single root node.
Add the root node to the DOM.
Convert the root node to a render location to which Aurelia can later add the hydrated nodes.
Create a ViewFactory
.
Create a ISyntheticView
using the view factory and activate.
In the first step we generate the DOM fragment using simple Web APIs. Our goal for this tutorial is to create the following DOM fragment.
To this end, we inject a IPlatform
instance to our App
instead of directly using the global Web APIs. This is recommended because it makes the testing easier.
Next we proceed to prepare the DOM fragment inside the add
method.
In the next step we need to add this fragment to the DOM and to this end we would like to use the div[ref=containerEl]
to be the parent of the template
.
Then we convert the template
to a render location. This process adds a marker, as render location, in the DOM where the hydrated nodes will be attached later.
After that we need to create a view factory from the template. The objective of creating a view factory is simply, as the name already suggests, to create a view later from it.
Note that to create the view factory we need a container, which is injected via the App
constructor.
With that our preparation is almost done. The next step involves creating a view from the view factory and activating it.
To activate the view however, we need to use a "parent" controller. This is needed as a hierarchical structure in maintained on controller-level. Because we are creating the view from App
, it makes sense to use the controller from the App
to this end. Aurelia adds a controller to every view custom element view model (as well as custom attribute view model) once the view model is created.
We use this controller to create the view from view factory.
In this step the view is created from the factory and the render location is set. Subsequently, the view is activated, which involves mainly binding the view with the given scope and attaching the hydrated nodes to the render location.
You may have noticed that we have stored the view in the App#view
property. Removing involves simply deactivating the view.
It also might be a good idea to dispose the view
from the dispose
hook of the view-model to ensure systematic disposal of the view and the associated resources.
You can see the live example below. It involves some trivial guard conditions; other than that it is mostly the same.
In this example, a new scope is created, to bind the view, for simplicity. However, if you want to avoid that you may reuse the same scope from the controller
itself (see ) or use that as parent scope depending on your need. To know more about scope and context refer the respective . Once the activation is complete you can see the hydrated nodes in DOM.