View models in Magento2

View models in Magento2

view models, Before Magento 2 we were overriding block if we want to pass additional information to our phtml file , which was resulting lots of unused process and codes , and still many of us are using overriding in magento2 as well and for that we are adding unnecessary dependency injection , because if you are overriding any block and if you want to add any new dependency injection then you have to add all dependency injection of parent block.

To avoid this, Magento 2 comes with new feature view models. Yes, now you can pass additional information to your phtml file without overriding block and without using unnecessary dependency injection.

How to Write view models?

First of all, you have to create a custom module. If you don’t know how to create custom module, you can check our previous blog.

Now create layout xml file where you want to use viewModel , In our Example we will create view models to display additional information at product detail page

create catalog_product_view.xml in layout folder and add below code

<referenceBlock name="product.info.details">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Mageacademy_ViewModelExample::product/view/details.phtml</argument>
            </action>
            <arguments>
                <argument name="view_model" xsi:type="object">Mageacademy\ViewModelExample\ViewModel\FirstViewModel</argument>
            </arguments>
        </referenceBlock>

Here we have override details.phtml template.and add view model in product info details block.

Now you need to create FirstViewModel class file as below

<?php
namespace Mageacademy\ViewModelExample\ViewModel;

use Magento\Framework\View\Element\Block\ArgumentInterface;

class FirstViewModel implements ArgumentInterface
{
    public function getAdditionalProductDetail()
    {
        return 'Additional Product Details';
    }
}

Here you need to extends ArgumentInterface to use view models, If you want to use constructor to add any dependency injection, you don’t need to add any other unnecessary class file in constructor.

Now you need to create phtml files as below

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/** @var \Magento\Catalog\Block\Product\View\Details $block */
?>
<?php
$viewModel = $block->getViewModel();

$additionalProductDetail =  $viewModel->getAdditionalProductDetail();
?>

<?php if ($detailedInfoGroup = $block->getGroupSortedChildNames('detailed_info', 'getChildHtml')) :?>
    <div class="product info detailed">
        <?php $layout = $block->getLayout(); ?>
        <div class="product data items" data-mage-init='{"tabs":{"openedState":"active"}}'>
            <?php foreach ($detailedInfoGroup as $name) :?>
                <?php
                $html = $layout->renderElement($name);
                if (!trim($html)) {
                    continue;
                }
                $alias = $layout->getElementAlias($name);
                $label = $block->getChildData($alias, 'title');
                ?>
                <div class="data item title"
                     data-role="collapsible" id="tab-label-<?= $block->escapeHtmlAttr($alias) ?>">
                    <a class="data switch"
                       tabindex="-1"
                       data-toggle="trigger"
                       href="#<?= $block->escapeUrl($alias) ?>"
                       id="tab-label-<?= $block->escapeHtmlAttr($alias) ?>-title">
                        <?= /* @noEscape */ $label ?>
                    </a>
                </div>
                <div class="data item content"
                     aria-labelledby="tab-label-<?= $block->escapeHtmlAttr($alias) ?>-title" id="<?= $block->escapeHtmlAttr($alias) ?>" data-role="content">
                    <?= /* @noEscape */ $html ?>
                    <?= $additionalProductDetail; ?>
                </div>
            <?php endforeach;?>
        </div>
    </div>
<?php endif; ?>

Here you can see we have added below code in above phtml file to use viewModel

$viewModel = $block->getViewModel();

$additionalProductDetail =  $viewModel->getAdditionalProductDetail();

Like this you can implement view models and avoid overriding block file

Hope this blog will be helpful for you, Visit us again and share with your friends.

Subscribe to our newsletter

Leave a Reply
Your email address will not be published. *