Magento 2: How can I use ifconfig or something similar to layout component
Pregunta
I created a boolean option (Yes / No) in Store -> Configuration, with which I can display or not the checkout sidebar.
The configuration path is: vendorname_sidebar/display/enabled
.
Below is a part about sidebar from the layout XML from checkout_index_index.xml
of the Checkout module.
How do I show or not show the sidebar in checkout depending on this setting in Store -> Configuration?
<item name="sidebar" xsi:type="array">
<item name="sortOrder" xsi:type="string">50</item>
<item name="component" xsi:type="string">Magento_Checkout/js/view/sidebar</item>
<item name="displayArea" xsi:type="string">sidebar</item>
...
</item>
Solución
In the answers to this question "Remove a UI component child via Layout XML" you can see how you can disable the sidebar UI component by XML. Now you do not want to do this this way, because then it would always be removed/disabled.
If you look at the complete layout XML in checkout_index_index.xml
, it looks something like this:
<page ........>
<body>
<referenceContainer name="content">
<block class="Magento\Checkout\Block\Onepage" name="checkout.root" template="onepage.phtml" cacheable="false">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="types" xsi:type="array">........</item>
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
........
<item name="children" xsi:type="array">
........
<item name="sidebar" xsi:type="array">
<item name="sortOrder" xsi:type="string">50</item>
<item name="component" xsi:type="string">Magento_Checkout/js/view/sidebar</item>
<item name="displayArea" xsi:type="string">sidebar</item>
<item name="config" xsi:type="array">
........
</item>
........
You see that the whole <item ...>
XML is part of a bigger <arguments>
structure that is a child of the <block class="Magento\Checkout\Block\Onepage" ...>
definition. This whole structure is converted to a PHP associative array and passed into the $data
argument of the constructor when creating this block class.
The jsLayout
is a UI Components definition and you could disable the sidebar component by setting componentDisabled
to true
in the config
.
If we look at the Magento\Checkout\Block\Onepage
constructor, we can see what happens to all this data. Also we see that there is an array argument layoutProcessors
.
public function __construct(
........
array $layoutProcessors = [],
array $data = []
) {
........
$this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : [];
$this->layoutProcessors = $layoutProcessors;
}
Now the jsLayout
is retreived from the Block by calling its getJsLayout()
method which runs the layout processors first before returning the data as JSON:
public function getJsLayout()
{
foreach ($this->layoutProcessors as $processor) {
$this->jsLayout = $processor->process($this->jsLayout);
}
return \Zend_Json::encode($this->jsLayout);
}
So, you should also add a layout processor via Dependency Injection (DI) in your module's etc/frontend/di.xml
:
<config ........>
<type name="Magento\Checkout\Block\Onepage">
<arguments>
<argument name="layoutProcessors" xsi:type="array">
<item name="sidebarSwitcher" xsi:type="object">Vendorname\Sidebar\Block\CheckoutOnepage\SidebarSwitcherProcessor</item>
</argument>
</arguments>
</type>
</config>
This \Vendorname\Sidebar\Block\CheckoutOnepage\SidebarSwitcherProcessor
class should implement \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
and (therefor) you should have a public method called process()
where you can disable the sidebar based on the config you mention:
namespace Vendorname\Sidebar\Block\CheckoutOnepage;
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface;
class SidebarSwitcherProcessor implements LayoutProcessorInterface
{
public function process($jsLayout) {
if (..... check config value .....) {
$jsLayout['components']['checkout']['children']['sidebar']['config']['componentDisabled'] = true;
}
return $jsLayout;
}
}
Otros consejos
For use Scope Config Interface on the component from checkout page, you must create a Plugin see below:
Below code is must in Vendorname/SidebarActivation/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
<plugin name="SidebarDisable" type="Vendorname\SidebarActivation\Plugin\SidebarDisable"/>
</type>
</config>
Below code is in Vendorname/SidebarActivation/Plugin/SidebarDisable.php
<?php
namespace Vendorname\SidebarActivation\Plugin;
use Magento\Checkout\Block\Checkout\LayoutProcessor;
/**
* Class SidebarDisable
*
* @package Vendorname\SidebarActivation\Plugin
*/
class SidebarDisable {
/**
* @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor
* @param array $jsLayout
*
* @return array
*/
public function afterProcess(
LayoutProcessor $processor,
array $jsLayout
){
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$enable = $objectManager->get('Magento\Framework\App\Config\ScopeConfigInterface')->getValue('sectionid/groupid/fieldid');
if($enable){
$jsLayout['components']['checkout']['children']['sidebar']['config']['componentDisabled'] = true;
}
return $jsLayout;
}
}