Let’s take a look at a few cases when it may be required to add a custom element. The main place is the admin panel. We might require the following elements:
- A column in a Grid;
- A form element;
- Config element as described in the system.xml file.
1. Grid
There are 2 ways to implement depending on how the column list is generated.
– Via xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<block class="Magento\Backend\Block\Widget\Grid" name="custom.grid" as="grid"> ... <arguments> <argument name="dataSource" xsi:type="object">MyVendor\MyExtension\Model\Resource\Grid\Collection</argument> ... </arguments> <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" name="custom.grid.columnSet" as="grid.columnSet"> ... <block class="Magento\Backend\Block\Widget\Grid\Column" as="is_active"> <arguments> <argument name="header" xsi:type="string" translate="true">Custom Column</argument> <argument name="index" xsi:type="string">customcolumn</argument> <argument name="renderer" xsi:type="string">MyVendor\MyExtension\Block\Adminhtml\Grid\Renderer\Customcolumn</argument> ... </arguments> </block> </block> </block> |
The column itself will be rendered by the standard block:
Magento\Backend\Block\Widget\Grid\Column
The collection will be generated via our resource:
MyVendor\MyExtension\Model\Resource\Grid\Collection
It is also possible to modify the filter of our custom column.
Column values will be rendered by our Block:
MyVendor\MyExtension\Block\Adminhtml\Grid\Renderer\Customcolumn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace MyVendor\MyExtension\Block\Adminhtml\Grid\Renderer; class Customcolumn extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer { ... public function render(\Magento\Framework\Object $row) { $value = parent::render($row); ... // any changes in value ... return $value; } } |
It is also possible to monitor and change not the column Abstract itself, but one of the already created external elements. For example:
Magento\Backend\Block\Widget\Grid\Column\Renderer\Checkbox,
or
Magento\Backend\Block\Widget\Grid\Column\Renderer\Date
Here you will find all the ready-to-use basic templates.
– inside of the block
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 36 37 38 |
<?php namespace BelVG\DropDownMenu\Block\Adminhtml\Item; class Grid extends \Magento\Backend\Block\Widget\Grid\Extended { ... public function __construct( \MyVendor\MyExtension\Model\Resource\Grid\CollectionFactory $collectionFactory, ... ) { $this->_collectionFactory = $collectionFactory; } protected function _prepareCollection() { $collection = $this->_collectionFactory->create(); /* @var $collection \MyVendor\MyExtension\Model\Resource\Grid\Collection */ ... $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { ... $this->addColumn( 'customcolumn', [ 'header' => __('Custom Column'), 'index' => 'customcolumn', 'renderer' => 'MyVendor\MyExtension\Block\Adminhtml\Grid\Renderer\Customcolumn’, .... ]); ... } .... } |
The render is a full match to the previous one.
2. Form
It is all simple here. The field can be declared as any type. You just need to replace the render block as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$field = $fieldset->addField( 'customfield', 'text', [ 'name' => 'customfield', 'title' => __('Custom Field'), ... ] ); $renderer = $this->getLayout()->createBlock( 'MyVendor\MyExtension\Block\Adminhtml\Form\Renderer\Customfield'' ); $field->setRenderer($renderer); |
Now let’s take a look at the structure of the render field:
MyVendor\MyExtension\Block\Adminhtml\Form\Renderer\Customfield
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php namespace MyVendor\MyExtension\Block\Adminhtml\Form\Renderer; class Customfield extends \Magento\Backend\Block\Widget\Form\Renderer\Fieldset\Element implements \Magento\Framework\Data\Form\Element\Renderer\RendererInterface { ... protected $_template = 'MyVendor_MyExtension::renderer/form/customfield.phtml'; ... public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element) { $this->_element = $element; $html = $this->toHtml(); ... return $html; } } |
It is possible either to process HTML inside the render function here or to replace the default template by adding the variable $_template with our template.
Besides the Abstract element we can also inherit and modify such elements as:
Magento\Backend\Block\Widget\Form\Element\Gallery
or
Magento\Backend\Block\Widget\Form\Element\Dependence
Controller and Model allow you to change the process of saving the custom field, for which this form has been generated. But there is nothing unusual here, so, let’s move on.
3. System.xml
3 class types can be set in the Config section:
– frontend_model – this block controls the frontend;
– backend_model – this model manages reading and saving;
– sourse_model – this model is used for fields that have a fixed number of values, described here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd"> <system> ... <section ...> ... <group ...> ... <field type=”...” ...> <label>Custom Field</label> <frontend_model>MyVendor\MyExtension\Block\System\Config\CustomFrontend</frontend_model> <backend_model>MyVendor\MyExtension\Model\System\Config\CustomBackend</backend_model> <source_model>MyVendor\MyExtension\Model\System\Config\CustomSource</source_model> ... </field> </group> </section> </system> </config> |
Of course, it is possible to not indicate each of the 3 classes, it depends on what exactly we are going to modify. Or we can indicate one of the default options, as described in the case with the sоurсe_mоdel: Magento\Config\Model\Config\Source\Yesno
– frontend_model
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace MyVendor\MyExtension\Block\System\Config; class CustomFrontend extends \Magento\Config\Block\System\Config\Form\Field { ... public function getElementHtml() { $html = parent::getElementHtml(); ... return $html; } } |
It is possible to customize one of the ready-made elements. For example:
Magento\Config\Block\System\Config\Form\Field\Image
or
Magento\Config\Block\System\Config\Form\Field\File
– backend_model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php namespace MyVendor\MyExtensionModel\System\Config; class CustomFrontend extends \Magento\Framework\App\Config\Value { protected function _afterLoad() { $value = $this->getValue(); ... $this->setValue($value); } public function beforeSave() { $value = $this->getValue(); ... $this->setValue($value); } } |
While customizing one of the standard elements we inherit one of the models here:
Magento\Config\Model\Config\Backend\ . . .
– source_model
This is, perhaps, the most popular type of customization: to define your own selection options for settings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php namespace MyVendor\MyExtension\Model\System\Config; class CustomSource implements \Magento\Framework\Option\ArrayInterface { public function toOptionArray() { return [ ['value' => 1, 'label' => __('Value 1')], ['value' => 0, 'label' => __('Value 2')], ... ]; } public function toArray() { return [ 0 => __('Value 1'), 1 => __('Value 2'), ... ]; } } |