If you need to add additional business logic to blocks for templates in Magento 2 you don’t need to extend blocks or add additional dependencies to the block now. Since Magento 2.2 you have ViewModels functionality for this purpose.
Let’s check how it works. For example, you want to add some additional business logic to the customer login page. In our example, let’s display additional data ‘Enter your email address‘ on the login form.
To do that we do not need to extend current block or create a new one. We do not need to modify our current block either. All we need to do is:
- Create
app/code/Vendor/Module_Name/ViewModel/CustomDataProvider.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php declare(strict_types=1); namespace Vendor\Module_Name\ViewModel; /** * Provides customer login form custom data. */ class CustomDataProvider implements \Magento\Framework\View\Element\Block\ArgumentInterface { /** * Returns custom data * * @return string */ public function getCustomData(): string { return 'Enter your email address'; } } |
Our new provider implements Magento\Framework\View\Element\Block\ArgumentInterface
2. Modify app/code/Magento/Customer/view/frontend/layout/customer_account_login.xml
1 2 3 4 5 6 7 8 |
<block class="Magento\Customer\Block\Form\Login" name="customer_form_login" template="Magento_Customer::form/login.phtml"> <container name="form.additional.info" as="form_additional_info"/> <!--added view model block--> <arguments> <argument name="view_model" xsi:type="object">Vendor\Module_Name\ViewModel\CustomDataProvider</argument> </arguments> <!--end of added view model block--> </block> |
Here we add our new CustomDataProvider
as a view_model
argument to Magento\Customer\Block\Form\Login
block.
3. Modify app/code/Magento/Customer/view/frontend/templates/form/login.phtml
template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** @var \Magento\Customer\Block\Form\Login $block */ <fieldset class="fieldset login" data-hasrequired="<?= $block->escapeHtml(__('* Required Fields')) ?>"> <div class="field note"><?= $block->escapeHtml(__('If you have an account, sign in with your email address.')) ?></div> <div><?= $block->getViewModel()->getCustomData()?></div> <div class="field email required"> ... </div> <div class="field password required"> ... </div> <?= $block->getChildHtml('form_additional_info') ?> <div class="actions-toolbar"> ... </div> </fieldset> |
Here $block->getViewModel()->getCustomData()
gets our new view model data provider and call its getCustomData method.
As a result we do not need to extend Magento\Customer\Block\Form\Login
block with all its dependencies and create a new block. We just pass our new class with additional logic as a view model argument to the block and call its methods in the template.