A free and open-source book on ZF3 for beginners

6.10. View Models and Page Composition

Earlier, when we wrote action methods for the controller classes, we used the ViewModel class as a variable container for passing the variables from controller to view template, and we also used the ViewModel for overriding the default view template name.

But, actually the ViewModel class is more than just a variable container plus view template name. In fact, it is closely related to the layout and page composition.

The third big capability of the view model class is that it allows for combining several view models in a tree-like structure. Each view model in the tree has the associated view template name and data variables that can be passed to the view template to control the process of rendering.

This feature is internally used by Zend Framework 3 when "combining" the layout view template and the view template associated with the controller's action method. ZF3 internally creates the view model for the layout template and assigns it with layout/layout view template name. When your controller's action method returns the ViewModel object, this object is attached as a child to the layout view model (see figure 6.12 for an example).

Figure 6.12. View models nested in a tree-like structure Figure 6.12. View models nested in a tree-like structure

The resulting process of page rendering is the following:

Table 6.5 gives the summary of the methods provided by the ViewModel class for the purpose of page composition:

Table 6.5. Methods of the ViewModel class for page composition
Method name Description
addChild() Adds a child view model.
getChildren() Gets the list of child view models.
hasChildren() Tests if the view model has children or not.
clearChildren() Removes all child view models.
count() Returns count of child view models.
getIterator() Returns the iterator for child view models.
setTerminal() Sets the terminal flag.
terminate() Tests whether the view model is terminal.
setCaptureTo() Sets the name of the variable for capturing the output.
setAppend() Sets the append flag.
isAppend() Tests whether to append this view model to another one.

Below, we provide the brief description of the methods presented in the table above.

The addChild(), getChild(), hasChildren() and clearChildren() methods are used for (respectively) adding a child view model to the parent one, retrieving the array of view models attached, testing if the view model is leaf (doesn't have children) and detaching all children.

The setCaptureTo() method allows to set the variable in the parent view template into which to inject the HTML markup code produced by a child view template. If two child view models use the same variable, the second one will overwrite the first one. The setAppend() method can be used when you need to inject the results of two or more view templates into a single placeholder variable. The next rendered view template will be appended to the variable's existing content. The view model returned by the controller is assigned the $content capture variable.

A view model can be marked as terminal with the setTerminal() method. The setTerminal() method takes a single flag parameter. If true, the view model is considered as terminal (top-level parent) and the renderer returns the output of the view template to the application, otherwise its parents are rendered as well. The method terminate() tests whether the view model is terminal or not.

The setTerminal() method is very useful in some situations, because with its help you can disable the rendering of the layout view template. If you return from controller the view model marked as terminal, the layout will not be applied. This can be used, for example, when you want to load part of a page asynchronously by an AJAX 18 request and need to insert its HTML code in the DOM tree of an existing page.

18) AJAX (stands for Asynchronous JavaScript and XML) is a capability provided by modern browsers which can be used to send data to, and retrieve data from, a server asynchronously (in background) without interfering with the display and behavior of the existing page.