Module 3. View Layer. Rendering

  • Overview
    • Templates
    • Blocks
    • Design Layout XML Schema
  • Rendering flow
    • Rendering Flow Aspects: View
    • Rendering Flow Aspects: Pages and Result Object
  • View elements
  • Block Architecture and Lifecycle
    • Block Inside
    • Lifecycle
  • Templates
    • Templates Initiation
    • Conventional Templates Location
    • Overriding Templates
    • Root template
    • Argument Values from Layout
  • Layout XML structure
    • <block>
    • <container>
    • The before and after attributes
    • <action>
    • <referenceBlock> and <referenceContainer>
    • <move>
    • <update>
    • <argument>

Overview

Templates

Magento 2 still uses PHTML files for templates. Unlike Magento 1.x, using PHTML is no longer the only option, any template system can be used, but for we will stick with PHTML for now as they come by default and cover all available themes.

Blocks

Blocks are classes to encapsulate reusable functionality responsible for rendering. Blocks usually instantiate models to trigger some rendering-related business logic, or to fetch necessary data for rendering.

Design Layout XML Schema

Layout XML files pull together the entire set of blocks template files to be rendered in browser. It also declares block hierarchy that allows to build a layout tree before rendering. Layout XML format evolved since Magento 1.x.

Rendering flow

The chart below shows a general process flow for rendering pages within a website. 

Rendering Flow Aspects: View

The \Magento\Framework\App\ViewInterface contains the following main methods:

  • loadLayoutUpdates()
  • renderLayout()
  • loadLayout()
  • getPage()
  • getLayout()

This interface now encapsulates logic that belonged to the action controller class in Magento 1.x. You have an access to the View object in the action controller by using $this->_view.

The \Magento\Framework\View\Layout class is an analog of the Mage_Core_Model_Layout class in Magento 1.x. This class together with a Processor class (\Magento\Framework\View\Layout\ProcessorInterface) implements the whole logic of loading, parsing and filtering layout XML files, generating layout XML for the current page, generating block instances, and setting the right parameters into them.

This mechanism is somewhat deprecated, Magento 2 has another rendering mechanism based on a Page object, that is going to substitute View infrastructure in the future releases.

There are two phases of rendering.

Phase One, loading layout, makes Magento load all XML layout, render them to build a list of instructions for block creation. Then, Magento creates a layout structure and instantiates blocks in it

Phase Two, when it’s time to render the loaded layout, Magento executes toHtml() methods of the root blocks and concatenates the result.

Rendering Flow Aspects: Pages and Result Object

A concept of result object is to use page object returned to the Application inside Application::launch() as a result of the rest of the request flow. The idea is to create a \Magento\Framework\View\Result\Page object in the action controller using \Magento\Framework\View\Result\PageFactory. If the Page object is returned in Application, it then is rendered using renderPage() method. 

This part of training is a bit inconsistent and incomplete at the moment, there was a contradictory information in the Fundamentals training, no info in the Developers documentation or any other resource. Use with care, and check the view rendering flow yourself on the first opportunity. Sorry for inconvenience!

View elements

There are three types of view elements in Magento 2:

  • Containers are logical wrappers very similar to \Magento\Framework\View\Element\Text\ListText, except there can be an instance of container, they are abstract concept
  • Blocks — almost same as in Magento 1.x
  • UiComponents — responsible for representing and rendering form elements. Implementation is in \Magento\Framework\View\Element\UiComponentInterface. Note that \Magento\Framework\View\Element\UiComponentInterface extends \Magento\Framework\View\Element\BlockInterface, which means UI components are blocks, too.

A containers:

  • doesn’t have any classes related to it
  • renders all its children
  • allows configuration of some attributes (e.g. wrapping tag, CSS class)

Block Architecture and Lifecycle

Every page consists of hierarchical structure of blocks. Layout does not define a location and shape of the blocks on a page, it just defines their sequence and hierarchy. How the blocks actually look on the page, depends on how they are rendered.

The role of the blocks in layout is adding content within the layout structure. Blocks are put to the layout as children to containers and to other blocks.

Block Inside

Every block in Magento 2 implements \Magento\Framework\View\Element\BlockInterface and is extends \Magento\Framework\View\Element\AbstractBlock.

The interface commands a block to implement public toHtml() method which is always called if the block needs to be rendered.

The AbstractBlock also introduces a number of important methods:

 

 

_prepareLayout()

A specific method that is executed when block is created. It is often redeclared in a specific block and contains init operations that happen at the moment layout is being built. It’s important to know it is called before toHtml()

addChild()

Adds a child block. Since block structure is hierarchical, there needs to be methods to add, remove, find and sort children.

_toHtml(), _beforeToHtml(), _afterToHtml()

These are methods that are executed right before, at the moment and after the rendering, they are called in toHtml() and are redeclared quite often in concrete blocks implementation.

toHtml()

This method is an implementation of rendering initially declared in BlockInterface.

This is how toHtml() method implemented in the AbstractBlock:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

/**

 * Produce and return block’s html output

 *

 * This method should not be overridden. You can override _toHtml() method in descendants if needed.

 *

 * @return string

 */

public function toHtml()

{

    $this->_eventManager->dispatch(‘view_block_abstract_to_html_before’, [‘block’ => $this]);

    if ($this->_scopeConfig->getValue(

        ‘advanced/modules_disable_output/’ . $this->getModuleName(),

        \Magento\Store\Model\ScopeInterface::SCOPE_STORE

    )) {

        return ;

    }

 

    $html = $this->_loadCache();

    if ($html === false) {

        if ($this->hasData(‘translate_inline’)) {

            $this->inlineTranslation->suspend($this->getData(‘translate_inline’));

        }

 

        $this->_beforeToHtml();

        $html = $this->_toHtml();

        $this->_saveCache($html);

 

        if ($this->hasData(‘translate_inline’)) {

            $this->inlineTranslation->resume();

        }

    }

    $html = $this->_afterToHtml($html);

 

    return $html;

}

While toHtml() method is declared as final in Magento 1.x, in Magento 2 it is not (in order to be able to write plugins, most probably). However, you must avoid redeclaring toHtml() directly.

The most important block type a developer should be aware of are as follows:

Block class

Description

\Magento\Framework\View\Element\Text

Text block, it allows you to add various portions of text using addText() and then render that text concatenated

\Magento\Framework\View\Element\Text\ListText

Text list block. All it does when being rendered is render its own children. It’s quite similar to the behavior of containers

\Magento\Framework\View\Element\Messages

Messages block. It provides an interface to set a collection of messages, or add messages one by one, and then it renders them with special wrapping based on a specific template

\Magento\Framework\View\Element\Redirect

Redirect block, it handles various browser-side redirections

\Magento\Framework\View\Element\Template

A very basic template block. Sometimes it’s just enough to have a block that can render itself based on a template you specify.

There are many ways to pass template to a block that is extended from \Magento\Framework\View\Element\Template. You can do it by

  • passing [‘template’ => ‘your-template.phtml’] as a second argument in the block constructor
  • calling $block->setTemplate(‘your-template.phtml’)
  • specifying a template as an attribute within <block> construct in the layout XML file. 

Lifecycle

It was already mentioned that block has two separate stages of its life. 

Block generation

Block rendering

  • Instances of all blocks declared in the layout are created
  • Structure is built and block children are set
  • Block’s _prepareLayout() is called for every block
  • Nothing is rendered at this point

As containers are not blocks and don’t have own instance, all that happens to a container at this point is assigning attributes from layout XML declaration

  • starts with calling Layout::getOutput()
  • a loop through every root block and container defined in the empty.xml layout XML file
  • every block’s toHtml() method is called
  • in case of containers, the process loops through all container’s children and concatenates their resulting rendering output
  • result of rendering is being concatenated into one string

Templates

Templates are snippets of HTML code provided as PHTML files that contain PHP instructions, local variable declarations and calls of class methods.

Templates Initiation

Templates are usually initiated in layout files. Each layout block has an associated template. The template is specified in the templateattribute of the layout instruction. For example, from <Magento_Catalog_module_dir>/view/frontend/layout/catalog_category_view.xml:

Example

<block class=“Magento\Catalog\Block\Category\View” name=“category.image” template=“Magento_Catalog::category/image.phtml”/> 

This means that the category.image block is rendered by the image.phtml template, which is located in the category subdirectory of the Magento_Catalog module templates directory.

The templates directory of Magento_Catalog is <Magento_Catalog_module_dir>/view/frontend/templates.

Conventional Templates Location

Templates are stored in the following locations:

  • Module templates: <module_dir>/view/frontend/templates/<path_to_templates>
  • Theme templates: <theme_dir>/<Namespace>_<Module>/templates/<path_to_templates>

Here <path_to_templates> might have several levels of directory nesting, or might be empty.

Examples:

  • <Magento_Catalog_module_dir>/view/frontend/templates/product/widget/new/content/new_grid.phtml
  • <Magento_Checkout_module_dir>/view/frontend/templates/cart.phtml

Overriding Templates

For template files with the same name, the following is true:

  • Theme templates override module templates
  • Child theme templates override parent theme templates.

This mechanism is the basis of the template customization concept in Magento application, to change the output defined by a certain default template, you need to overriding one in your custom theme.

Root template

Magento 2 has a special template which serves as root template for all pages in the application: <Magento_Theme_module_dir>/view/base/templates/root.phtml. Unlike other templates, root.phtml contains the doctype specification and contributes to <head> and <body> sections of all pages rendered by Magento application.

Similarly to other templates, root.phtml can be overridden in a theme.

Argument Values from Layout

Arguments values set in a layout file can be accessed in templates using the get{ArgumentName}() and has{ArgumentName}() methods.

Layout XML structure

<block>

Defines a block.

Details: A block is a unit of page output that renders some distinctive content – a piece of information, a user interface element – anything visually tangible for the end-user. Blocks employ templates to generate HTML. Examples of blocks include a category list, a mini cart, product tags, and product listing.

Attribute

Description

Values

Required?

class

Name of a class that implements rendering of a particular block. An object of this class is responsible for actual rendering of block output.

class name

yes

name

Name that can be used to address the block to which this attribute is assigned. The name must be unique per generated page. If not specified, an automatic name will be assigned in the format ANONYMOUS_n

0-9, A-Z, a-z, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive.

no

before

Used to position the block

before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting.

Possible values: element name or dash (-)

no

after

Used to position the block after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting.

Possible values: element name or dash (-)

no

template

A template that represents the functionality of the block to which this attribute is assigned.

template file name

no

as

An alias name that serves as identifier in the scope of the parent element.

0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive.

no

cacheable

Defines whether a block element is cacheable. This can be used for development purposes and to make needed elements of the page dynamic.

true or false

no

To pass parameters use the <argument> instruction.

<container>

A structure without content that holds other layout elements such as blocks and containers.

Details: A container renders child elements during view output generation. It can be empty or it can contain an arbitrary set of <container>and <block> elements.

Attribute

Description

Values

Required?

name

A name that can be used to address the container in which this attribute is assigned. The name must be unique per generated page.

A-Z, a-z, 0-9, underscore (_), period (.), dash (-). Should start with a letter. Case-sensitive.

yes

label

An arbitrary name to display in the web browser.

any

no

before

Used to position the container before an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block before all other elements of its level of nesting.

Possible values: element name or dash (-).

no

after

Used to position the container after an element under the same parent. The element name or alias name is specified in the value. Use dash (-) to position the block after all other elements of its level of nesting.

Possible values: element name or dash (-).

no

as

An alias name that serves as identifier in the scope of the parent element.

0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive.

no

output

Defines whether to output the root element. If specified, the element will be added to output list. (If not specified, the parent element is responsible for rendering its children.)

Any value except the obsoletetoHtml. Recommended value is1.

no

htmlTag

Output parameter. If specified, the output is wrapped into specified HTML tag.

Any valid HTML 5 tag.

no

htmlId

Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect.

Any valid HTML 5 <id> value.

no

htmlClass

Output parameter. If specified, the value is added to the wrapper element. If there is no wrapper element, this attribute has no effect.

Any valid HTML 5 <class> value.

no

Sample of usage in layout:

1

2

3

4

5

<!– … –>

<container name=“div.sidebar.additional” htmlTag=“div” htmlClass=“sidebar sidebar-additional” after=“div.sidebar.main”>

    <container name=“sidebar.additional” as=“sidebar_additional” label=“Sidebar Additional”/>

</container>

<!– … –>

This would add a new column to the page layout.

The before and after attributes

To help you to position elements in a specific order suitable for design, SEO, usability, or other requirements, Magento software provides the before and after layout attributes.

These optional attributes can be used in layout XML files to control the order of elements in their common parent. The following tables give a detailed description of the results you can get using the before and after attributes. The first table uses a block a as positioned element.

Attribute

Value

Description

before

Dash (-)

The block displays before all other elements in its parent node.

before

[element name]

The block displays before the named element.

before

empty value or [element name] is absent

Use the value of after. If that value is empty or absent as well, the element is considered as non-positioned.

after

Dash (-)

The block displays after all other elements in its parent node.

after

[element name]

The block displays after the named element.

after

empty value or [element name] is absent

Use the value of before. If that value is empty or absent as well, the block is considered as non-positioned.

Examples:

Situation

Result

Both before and after attributes are present

after takes precedence.

Both before and after attributes are absent or empty

The element is considered as non-positioned. All other elements are positioned at their specified locations. The missing element displays at a random position that doesn’t violate requirements for the positioned elements.

Several elements have before or after set to dash (-)

All elements display at the top (or bottom, in case of the after attribute), but the ordering of group of these elements is undefined.

The before or after attribute’s value refers to an element that is not located in the parent node of the element being defined.

The element displays at a random location that doesn’t violate requirements for the correctly positioned elements.

<action>

The <action> instruction is deprecated. If the method implementation allows, use the <argument> for <block> or <referenceBlock> to access block public API.

Calls public methods on the block API.

Details: Used to set up the execution of a certain method of the block during block generation; the <action> node must be located in the scope of the <block> node.

Example

1

2

3

4

5

6

7

8

<block class=“Magento\Module\Block\Class” name=“block”>

    <action method=“setText”>

        <argument name=“text” translate=“true” xsi:type=“string”>Text</argument>

    </action>

    <action method=“setEnabled”>

        <argument name=“enabled” xsi:type=“boolean”>true</argument>

    </action>

</block>

The <action> child nodes are translated into block method arguments. Child nodes names are arbitrary. If there are two or more nodes with the same name under <action>, they are passed as one array.

In the previous example, the value of <arg1> is passed as the first argument and <arg2> values are passed as array(‘one’, ‘two’). The list of all available methods depends on the block implementation (for example, the public method of the block class).

Attribute

Description

Values

Required?

method

Name of the public method of the block class this tag is located in that is called during block generation.

block method name

yes

To pass parameters, use the <argument> instruction.

<referenceBlock> and <referenceContainer>

Updates in <referenceBlock> and <referenceContainer> are applied to the corresponding <block> or <container>.

For example, if you make a reference by <referenceBlock name=”right”>, you’re targeting the block <block name=”right”>.

To pass parameters to a block use the <argument> instruction.

Attribute

Description

Values

Required?

remove

Allows to remove or cancel the removal of the element. When a container is removed, its child elements are removed as well.

The remove attribute is optional and its default value is false.

This implementation allows you to cancel removal of a block or container in your layout by setting remove attribute value to false. 

Example

1

<referenceBlock name=“block.name” remove=“true” />

true/false

no

display

Allows you to disable rendering of specific block or container with all its children (both set directly and by reference). The block’s/container’s and its children’ respective PHP objects are still generated and available for manipulation.

The display attribute is optional and its default value is true.

You are always able to overwrite this value in your layout. In situation when remove value is true, the display attribute is ignored. 

Example

1

<referenceContainer name=“container.name” display=“false” />

true/false

no

<move>

Sets the declared block or container element as a child of another element in the specified order.

Example

1

<move element=“name.of.an.element” destination=“name.of.destination.element” as=“new_alias” after=“name.of.element.after” before=“name.of.element.before”/>

The <move> is skipped if the element to be moved is not defined.

If the as attribute is not defined, the current value of the element alias is used. If that is not possible, the value of the name attribute is used instead.

During layout generation, the <move> instruction is processed before the <remove> instruction. This means if any elements are moved to the element scheduled for removal, they will be removed as well.

Attribute

Description

Values

Required?

element

Name of the element to move.

element name

yes

destination

Name of the target parent element.

element name

yes

as

Alias name for the element in the new location.

0-9, A-Z, a-z, underscore (_), period (.), dash (-). Case-sensitive.

no

after | before

Specifies the element’s position relative to siblings. Use dash (-) to position the block before or after all other siblings of its level of nesting. If the attribute is omitted, the element is placed after all siblings.

element name

no

<update>

Includes a certain layout file. Used as follows:

Example

1

<update handle=“{name_of_handle_to_include}”/>

The specified handle is “included” and executed recursively.

<argument>

Used to pass an argument.

Attribute

Description

Values

Required?

name

Argument name.

unique

yes

xsi:type

Argument type.

string|boolean|object|number|null|array

yes

translate

 

true|false

no

To pass multiple arguments use the following construction:

<arguments>

   <argument></argument>

   <argument></argument>

   

</arguments>

To pass an argument that is an array use the following construction:

<argument>

   <item></item>

   <item></item>

   

</argument>

Arguments values set in a layout file can be accessed in templates using the get{ArgumentName}() and has{ArgumentName}() methods. The latter returns a boolean defining whether there’s any value set. {ArgumentName} is obtained from the name attribute the following way: for getting the value of <argument name=”some_string”> the method name is getSomeString().

Example: Setting a value of css_class in the <Magento_Theme_module_dir>/view/frontend/layout/default.xml layout file:

Example

1

2

3

4

5

<!– … –>

<arguments>

    <argument name=“css_class” xsi:type=“string”>header links</argument>

</arguments>

<!– … –>

Using the value of css_class in <Magento_Theme_module_dir>/view/frontend/templates/html/title.phtml:

Example

1

2

3

// …

$cssClass = $this->getCssClass() ? ‘ ‘ . $this->getCssClass() : ;

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s