Modular Frontend

This article provides information on Pages and Widgets, the Pages module and how the Pages module can be extended. Real-life examples included into the article will help you to understand the concept better.

General Information

Pages

Pages are the main concept of modular front-end (Yves) which splits code into modules. A Page module represents a set of pages displayed under some or similar URLs that logically belong together.

As an example, we consider Product Detail Page as one Page module which is responsible for displaying products and their basic information.

Another Page module example would be any customer related pages, like Login, Register, Profile, Addresses. These are several different pages. Each page is responsible for something specific from the customer domain, so it's natural to group them under the same module.

We group pages under a Page module when they are related to the same domain.

Widgets

Meanwhile, Page modules implement only feature basics, while Widgets provide optional extensions for them.

Product Detail Page shows basic product information, like the name, description and attributes of the product. But there are lots of optional features that can appear on the same page. The most commonly used examples are product image, price, availability, options, groups, rating, relations, an much more.

The Pages and Widgets concept offers a solution to tailor projects to their custom needs.

When you get the general understanding of the Pages/Widgets concept, its time to investigate how the Pages module looks like, why and how the module can be extended.

Page Module Appearance and Pages Extension

A Page module typically contains a ControllerProvider plugin for routing (see URL Routing) and some Controllers with their twig templates (see Controllers and Actions). The implementation scope of a Page module should be decided individually, depending on its need of re-usability.

The more generic a Page module is the more it can be reused, but also it needs more extension points this way.

As more features you need to have on in your Page module, as much you need to extend it.

To extend a Page with an additional functionality you use Widgets. When you extend the front-end by rendering a template fragment in a template of a controller action, you need to specify the exact place of each extension point on template level.

Before you start using the widget system, make sure to register the following plugins:

Learn how to implement a Widget here.

Widget Twig Tag Reference

{% widget WIDGET_EXPRESSION args WIDGET_ARGUMENTS use TWIG_TEMPLATE_PATH with TWIG_PARAMETERS only %}
	{% block WIDGET_BLOCK_N %}
		{{ parent() }}
	{% endblock %}
{% elsewidget ... %}
{% nowidget %}
	WIDGET_FALLBACK
{% endwidget %}
Tag Description Additional Comments
{% widget ... %}...{% endwidget %} Required twig tag to render a widget. A widget is rendered only when it can be found in the local or global widget registry.
WIDGET_EXPRESSION Can be a string that represents the name of the widget or an instance of a widget. This argument is required.
args WIDGET_ARGUMENTS Array of arguments that the widget is initialized with (by constructor() of new widgets or by initialize() method of old widget plugins). This parameter is only available when Š®WIDGET_EXPRESSION was not an instance of a widget. This parameter is optional, depending if the widget object to be initialized requires any arguments or not.
use TWIG_TEMPLATE_PATH Render the widget with a different template then defined by the widget. TWIG_TEMPLATE_PATH is a string that represents a valid path for a twig template that can be loaded. This parameter is optional.
with TWIG_PARAMETERS Pass an associative array of variables for the scope of the rendered widget twig blocks. This parameter is optional.
{% block WIDGET_BLOCK_N %}{% endblock %} Twig blocks to overwrite/customize blocks of the twig template to be rendered. {{ parent() }} can be used to render the original content of a block. This tag is optional.
only Optional argument to reduce the context of the template to be rendered to only the provided TWIG_PARAMETERS. By convention, in Spryker core we always provide this argument to prevent mixing template scopes.
{% elsewidget ... %} Optional twig tag to render a widget when the previous widget(s) were not found. Has the same parameters as the base widget tag including WIDGET_BLOCK_N. Listing multiple elsewidget tags will render the first widget that is found.
{% nowidget %} WIDGET_FALLBACK Optional twig tag to render any content (WIDGET_FALLBACK), when no widget is found by the widget tag. N/A

findWidget() Twig Function Reference

{% set widget = findWidget(WIDGET_NAME, WIDGET_ARGUMENTS) %}
 
{{ widget.WIDGET_PARAMETER_N ?? null }}
Tag Description Additional Comments
findWidget(WIDGET_NAME) Find a widget by name and return it as an object. When a widget is not found, null will be returned instead.
WIDGET_ARGUMENTS Array of arguments that the widget is initialized with (by constructor() of new widgets or by initialize() method of old widget plugins). This parameter is optional, depending if the widget object to be initialized requires any arguments or not.
widget.WIDGET_PARAMETER_N ?? null Get parameters of the widget through its ArrayAccess interface. The ?? check is required in all cases to prevent errors of non-existing widgets.

Deprecations

The Page and Widget concepts were introduced in spryker/kernel: 3.16.0 module version and originally Widgets were implemented as Yves plugins. Later, in 3.24.0 version of the Kernel module the widget plugins were deprecated. They started to be used in their own domain called Widget. Use the following documentation in case you are on a lower Kernel version.

Widget Plugins

Widget Plugins are scoped to a single use case. It's the main difference from Widgets which could be called from different Pages.

Widgets are implemented on demand of an extension of a template.

Before you start using the widget plugin system, make sure to register the \SprykerShop\Yves\ShopApplication\Plugin\Provider\WidgetServiceProvider in your YvesBoostrap.

<?php
 
namespace Pyz\Yves\ShopApplication;
 
use SprykerShop\Yves\ShopApplication\Plugin\Provider\WidgetServiceProvider;
use SprykerShop\Yves\ShopApplication\YvesBootstrap as SprykerYvesBootstrap;
 
class YvesBootstrap extends SprykerYvesBootstrap
{
	/**
	 * @return void
	 */
	protected function registerServiceProviders()
	{
		$this->application->register(new WidgetServiceProvider());
	}
}

Learn how to create a Widget Plugin here.