Here we learn how to add or create a UI-Select field using the block method on the Admin form.
Let’s start step by step.
You must have installed Magento 2 custom Module on which you are going to implement this.
Step 1: We need to create the layout file to define the admin form in view/adminhtml/layout/webkulblog_account_edit.xml :
<?xml version="1.0"?> <!-- /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="styles"/> <update handle="editor"/> <body> <referenceBlock name="menu"> <action method="setActive"> <argument name="itemId" xsi:type="string"> Webkul_Custom:webkulblog </argument> </action> </referenceBlock> <referenceBlock name="page.title"> <action method="setTitleClass"> <argument name="class" xsi:type="string"> complex </argument> </action> </referenceBlock> </body> </page>
Step 2: Create the block file, Webkul\Custom\Block\Adminhtml\Account\Edit
.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Block\Adminhtml\Account; class Edit extends \Magento\Backend\Block\Widget\Form\Container { /** * Initialize * * @return void */ protected function _construct() { $this->_objectId = 'entity_id'; $this->_blockGroup = 'Webkul_Custom'; $this->_controller = 'adminhtml_account'; parent::_construct(); if ($this->_isAllowedAction('Webkul_Custom::accountedit')) { $this->buttonList->update('save', 'label', __('Save Account')); } else { $this->buttonList->remove('save'); } $this->buttonList->remove('delete'); $this->buttonList->remove('reset'); } /** * Retrieve text for header element depending on loaded Group * * @return \Magento\Framework\Phrase */ public function getHeaderText() { return __('New Blog Account'); } /** * Check permission for passed action * * @param string $resourceId * @return bool */ protected function _isAllowedAction($resourceId) { return $this->_authorization->isAllowed($resourceId); } }
Step 3: Create the block file, Webkul\Custom\Block\Adminhtml\Account\Edit
\Tabs.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Block\Adminhtml\Account\Edit; class Tabs extends \Magento\Backend\Block\Widget\Tabs { /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder * @param \Magento\Backend\Model\Auth\Session $authSession * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Framework\Json\EncoderInterface $jsonEncoder, \Magento\Backend\Model\Auth\Session $authSession, array $data = [] ) { parent::__construct($context, $jsonEncoder, $authSession, $data); } /** * Construct * * @return void */ protected function _construct() { parent::_construct(); $this->setId('blog_account_tab'); $this->setDestElementId('edit_form'); $this->setTitle(__('Blog Account Information')); } /** * Prepare Layout * * @return $this */ protected function _prepareLayout() { $block = \Webkul\Custom\Block\Adminhtml\Account\Edit\Tab\BlogAccount::class; $this->addTab( 'blog_account_info', [ 'label' => __('Blog Account'), 'content' => $this->getLayout()->createBlock($block, 'blog_account_info')->toHtml() ] ); return parent::_prepareLayout(); } }
Step 4: Create the block file, Webkul\Custom\Block\Adminhtml\Account\Edit
\Tab\BlogAccount.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Block\Adminhtml\Account\Edit\Tab; use Magento\Backend\Block\Widget\Form\Generic; use Magento\Backend\Block\Widget\Tab\TabInterface; use Webkul\Custom\Block\Adminhtml\Widget\Form\Element\FilterSelect; class BlogAccount extends Generic implements TabInterface { /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Data\FormFactory $formFactory * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Data\FormFactory $formFactory, array $data = [] ) { parent::__construct($context, $registry, $formFactory, $data); } /** * Prepare form * * @return $this */ protected function _prepareForm() { $model = $this->_coreRegistry->registry('business_list_model'); $form = $this->_formFactory->create(); $fieldset = $form->addFieldset( 'base_fieldset', ['legend' => __('Blog Account'), 'class' => 'fieldset-wide'] ); $fieldset->addType('filterselect', FilterSelect::class); if ($model->getId()) { $fieldset->addField('entity_id', 'hidden', ['name' => 'entity_id']); } $fieldset->addField( 'user_name', 'text', [ 'name' => 'user_name', 'label' => __('User Name'), 'title' => __('User Name'), 'required' => true, 'note' => __('Set the unique name for account.') ] ); $fieldset->addField( 'access_data', 'filterselect', //custom type [ 'name' => 'access_data', 'label' => __('Access data'), 'options' => $this->getOptions(), 'multiple' => true, 'required' => true, ] ); if (!empty($model->getData())) { $data = $model->getData(); if (isset($data['access_data'])) { $data['access_data'] = explode(',', $data['access_data'] ?? ''); } $form->setValues($data); } $this->setForm($form); return parent::_prepareForm(); } /** * Get options * * @return array */ public function getOptions() { return [ ["value" => "1", "label" => "Customer"], ["value" => "2", "label" => "Admin"], ["value" => "3", "label" => "Seller"], ["value" => "4", "label" => "Guest"], ]; } /** * Prepare label for tab * * @return \Magento\Framework\Phrase */ public function getTabLabel() { return __('Blog Account'); } /** * Prepare title for tab * * @return \Magento\Framework\Phrase */ public function getTabTitle() { return __('Blog Account'); } /** * CanShowTab * * @return bool */ public function canShowTab() { return true; } /** * IsHidden * * @param bool */ public function isHidden() { return false; } /** * Check permission for passed action * * @param string $resourceId * @return bool */ protected function _isAllowedAction($resourceId) { return $this->_authorization->isAllowed($resourceId); } }
Step-5: Add the custom type in block form using $fieldset->addType(‘filterselect’, FilterSelect::class);, This custom type’s “filterselect” field data handling and rendering by block file : Webkul\Custom\Block\Adminhtml\Widget\Form\Element\FilterSelect.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Block\Adminhtml\Widget\Form\Element; use Magento\Framework\Data\Form\Element\AbstractElement; use Magento\Framework\Data\Form\Element\Factory as ElementFactory; use Magento\Framework\Data\Form\Element\CollectionFactory; use Magento\Framework\Escaper; use Magento\Framework\Serialize\SerializerInterface; /** * Class FilterSelect. */ class FilterSelect extends AbstractElement { /** * @var \Magento\Framework\View\LayoutInterface */ protected $layout; /** * @var SerializerInterface */ protected $serializer; /** * Constructor. * * @param ElementFactory $elementFactory * @param CollectionFactory $collectionFactory * @param Escaper $escaper * @param \Magento\Framework\View\LayoutInterface $layout * @param SerializerInterface $serializer * @param array $data */ public function __construct( ElementFactory $elementFactory, CollectionFactory $collectionFactory, Escaper $escaper, \Magento\Framework\View\LayoutInterface $layout, SerializerInterface $serializer, array $data = [] ) { parent::__construct($elementFactory, $collectionFactory, $escaper, $data); $this->layout = $layout; $this->serializer = $serializer; $this->setType('filterselect'); } /** * @inheritdoc */ public function getElementHtml() { $html = $this->layout->createBlock(\Magento\Framework\View\Element\Template::class) ->setTemplate('Webkul_Custom::business/filterselect.phtml') ->setTemplateConfiguration($this->getCustomConfiguration()) ->toHtml(); $html .= $this->getAfterElementHtml(); return $html; } /** * Get custom configuration * * @return string */ public function getCustomConfiguration() { $data = $this->getData(); $defultConfiguration = $this->getDefaultConfiguration(); foreach($defultConfiguration as $key => $configuration){ if(isset($data[$key])) { $defultConfiguration[$key] = $data[$key]; } } return $this->serializer->serialize($defultConfiguration); } /** * Get defaults configuration * * @return array */ public function getDefaultConfiguration() { $data = $this->getData(); $configurationData =[ "options" => [], "listVisible" => false, "value" => [], 'filterOptions' => true, "chipsEnabled" => true, "multiple" => true, "showFilteredQuantity" => true, "showCheckbox" => false, "filterRateLimit" => 500, "closeBtn" => true, "closeBtnLabel" => __('Done'), "quantityPlaceholder" => __('options'), "hoverClass" => '_hover', "selectedPlaceholders" => [ "defaultPlaceholder" => __('Select...'), "lotPlaceholders" => __('Selected') ], "component" => "Magento_Ui/js/form/element/ui-select", "template" => "Webkul_Custom/filterselect", // custom template file "elementData" => [ "name" => $this->getName(), "id" => $this->getHtmlId(), ], "required_entry" => isset($data['required']) ? $data['required'] : false ]; return $configurationData; } }
Step 6: Create a phtml template file which is mentioned in getElementHtml() method of Step 5, view/adminhtml/templates/business/filterselect.phtml
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ ?> <div data-bind="scope: 'customFilterSelect'"> <!-- ko template: getTemplate() --><!-- /ko --> </div> <script type="text/x-magento-init"> { "*": { "Magento_Ui/js/core/app": { "components": { "customFilterSelect": <?= /* @noEscape */ $block->getTemplateConfiguration() ?> } } } } </script>
Step 7: Create a custom template file which is mentioned in getDefaultConfiguration() method of Step 5, view/adminhtml/web/template/filterselect.html
<div class="admin__action-multiselect-wrap action-select-wrap" tabindex="0" data-bind=" attr: { id: uid }, css: { _active: listVisible, 'admin__action-multiselect-tree': isTree() }, event: { focusin: onFocusIn, focusout: onFocusOut, keydown: keydownSwitcher }, outerClick: outerClick.bind($data) "> <!-- ko if: (!hasData() && multiple) --> <input type="hidden" data-bind=" attr: { id: elementData.id, name: elementData.name+'[]', value: null } "> <!-- /ko --> <!-- ko ifnot: chipsEnabled --> <div class="action-select admin__action-multiselect" data-role="advanced-select" data-bind=" css: {_active: multiselectFocus}, click: function(data, event) { toggleListVisible(data, event) } "> <div class="admin__action-multiselect-text" data-role="selected-option" data-bind="text: setCaption()"> </div> <!-- ko foreach: { data: getSelected(), as: 'option'} --> <input type="hidden" data-bind=" attr: { id: $parent.elementData.id + value, name: $parent.elementData.name +'[]', value: value } "> <!-- /ko --> </div> <!-- /ko --> <!-- ko if: chipsEnabled --> <div class="action-select admin__action-multiselect" data-role="advanced-select" data-bind=" css: {_active: multiselectFocus}, click: function(data, event) { toggleListVisible(data, event) } "> <div class="admin__action-multiselect-text" data-bind=" visible: !hasData(), i18n: selectedPlaceholders.defaultPlaceholder "> </div> <!-- ko foreach: { data: getSelected(), as: 'option'} --> <span class="admin__action-multiselect-crumb"> <span data-bind="text: label"> </span> <button class="action-close" type="button" data-action="remove-selected-item" tabindex="-1" data-bind="click: $parent.removeSelected.bind($parent, value) "> <span class="action-close-text" translate="'Close'"></span> </button> </span> <input type="hidden" data-bind=" attr: { id: $parent.elementData.id + value, name: $parent.elementData.name +'[]', value: value } "> <!-- /ko --> </div> <!-- /ko --> <div class="action-menu" data-bind="css: { _active: listVisible } "> <!-- ko if: filterOptions --> <div class="admin__action-multiselect-search-wrap"> <input class="admin__control-text admin__action-multiselect-search" data-role="advanced-select-text" type="text" data-bind=" event: { keydown: filterOptionsKeydown }, attr: {id: uid+2}, valueUpdate: 'afterkeydown', value: filterInputValue, hasFocus: filterOptionsFocus "> <label class="admin__action-multiselect-search-label" data-action="advanced-select-search" data-bind="attr: {for: uid+2} "> </label> <div if="itemsQuantity" data-bind="text: itemsQuantity" class="admin__action-multiselect-search-count"> </div> </div> <!-- /ko --> <ul class="admin__action-multiselect-menu-inner _root" data-bind=" event: { scroll: function(data, event){onScrollDown($data, event)} } "> <!-- ko foreach: { data: options, as: 'option'} --> <li class="admin__action-multiselect-menu-inner-item _root" data-bind="css: { _parent: $data.optgroup }" data-role="option-group"> <div class="action-menu-item" data-bind=" css: { _selected: $parent.isSelected(option.value), _hover: $parent.isHovered(option, $element), _expended: $parent.getLevelVisibility($data), _unclickable: $parent.isLabelDecoration($data), _last: $parent.addLastElement($data), '_with-checkbox': $parent.showCheckbox }, click: function(data, event){ $parent.toggleOptionSelected($data, event); }, clickBubble: false "> <!-- ko if: $data.optgroup && $parent.showOpenLevelsActionIcon--> <div class="admin__action-multiselect-dropdown" data-bind=" click: function(event){ $parent.openChildLevel($data, $element, event); }, clickBubble: false "> </div> <!-- /ko--> <!--ko if: $parent.showCheckbox--> <input class="admin__control-checkbox" type="checkbox" tabindex="-1" data-bind="attr: { 'checked': $parent.isSelected(option.value) }"> <!-- /ko--> <label class="admin__action-multiselect-label"> <span data-bind="text: option.label"></span> <span if="$parent.getPath(option)" class="admin__action-multiselect-item-path" data-bind="text: $parent.getPath(option)"></span> </label> </div> <!-- ko if: $data.optgroup --> <!-- ko template: {name: $parent.optgroupTmpl, data: {root: $parent, current: $data}} --> <!-- /ko --> <!-- /ko--> </li> <!-- /ko --> </ul> <!-- ko if: $data.closeBtn --> <div class="admin__action-multiselect-actions-wrap"> <button class="action-default" data-action="close-advanced-select" type="button" data-bind="click: outerClick"> <span translate="closeBtnLabel"></span> </button> </div> <!-- /ko --> </div> </div> <!-- ko if: ($data.getSelected().length == 0 && required_entry) --> <input type="hidden" data-bind=" attr: { name: 'custom_required', class: 'required-entry', value: null } "> <!-- /ko -->
Step 8: Create a block file for form, Webkul\Custom\Block\Adminhtml\Account\Edit\Form.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Block\Adminhtml\Account\Edit; class Form extends \Magento\Backend\Block\Widget\Form\Generic { /** * Init form * * @return void */ protected function _construct() { parent::_construct(); $this->setId('blog_account_form'); $this->setTitle(__('Blog Account Information')); } /** * Prepare form * * @return $this */ protected function _prepareForm() { $model = $this->_coreRegistry->registry('business_list_model'); $form = $this->_formFactory->create( [ 'data' => [ 'id' => 'edit_form', 'enctype' => 'multipart/form-data', 'action' => $this->getData('action'), 'method' => 'post' ] ] ); if (!empty($model->getData())) { $data = $model->getData(); if (isset($data['access_data'])) { $data['access_data'] = explode(',', $data['access_data'] ?? ''); } $form->setValues($data); } $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } }
Step 9: Create a controller file for layout webkulblog_account_edit.xml , Webkul\Custom\Controller\Adminhtml\Account\Edit.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Controller\Adminhtml\Account; use Magento\Framework\Controller\ResultFactory; use Webkul\Custom\Block\Adminhtml\Account\Edit as AccountEdit; use Webkul\Custom\Block\Adminhtml\Account\Edit\Tabs; class Edit extends \Magento\Backend\App\Action { /** * @var string */ public const ADMIN_RESOURCE = "Webkul_Custom::accountedit"; /** * @var \Magento\Framework\Registry */ private $registry; /** * @var \Webkul\Custom\Model\BusinessListFactory */ protected $businessListFactory; /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $registry */ public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\Registry $registry, \Webkul\Custom\Model\BusinessListFactory $businessListFactory ) { $this->registry = $registry; $this->businessListFactory = $businessListFactory; parent::__construct($context); } /** * Execute * * @return \Magento\Backend\Model\View\Result\Page */ public function execute() { try { $params = $this->getRequest()->getParams(); $businessListModel = $this->businessListFactory->create(); if (isset($params['entity_id']) && $params['entity_id']) { $businessListModel->load($params['entity_id']); if (!$businessListModel->getId()) { $this->messageManager->addError(__('Requested account currently not available.')); $resultRedirect = $this->resultRedirectFactory->create(); return $resultRedirect->setPath('*/*/'); } } $this->registry->register('business_list_model', $businessListModel); $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); $resultPage->setActiveMenu('Webkul_Custom::webkulblog'); $resultPage->getConfig()->getTitle()->prepend(__('Account')); $resultPage->addContent($resultPage->getLayout()->createBlock(AccountEdit::class)); $resultPage->addLeft($resultPage->getLayout()->createBlock(Tabs::class)); return $resultPage; } catch (\Exception $e) { $this->messageManager->addError($e->getMessage()); $this->_redirect('*/*/'); } } /** * Check for is allowed * * @return boolean */ protected function _isAllowed() { return $this->_authorization->isAllowed(self::ADMIN_RESOURCE); } }
Step 10: Create a controller file for the save selected option, Webkul\Custom\Controller\Adminhtml\Account\Save.php
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Custom * @author Webkul * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Custom\Controller\Adminhtml\Account; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; use Magento\Framework\View\Result\PageFactory; class Save extends Action { /** * @var Magento\Framework\View\Result\PageFactory */ protected $resultPageFactory; /** * @var Webkul\Custom\Model\BusinessListFactory */ protected $businessListFactory; /** * @var \Magento\Framework\Registry */ protected $coreRegistry = null; /** * @param Context $context * @param PageFactory $resultPageFactory * @param \Webkul\Custom\Model\BusinessListFactory $businessListFactory * @param \Magento\Framework\Registry $coreRegistry */ public function __construct( Context $context, PageFactory $resultPageFactory, \Webkul\Custom\Model\BusinessListFactory $businessListFactory, \Magento\Framework\Registry $coreRegistry ) { parent::__construct($context); $this->resultPageFactory = $resultPageFactory; $this->businessListFactory = $businessListFactory; $this->coreRegistry = $coreRegistry; } /** * Save User Data * * @return \Magento\Framework\App\Response\Http */ public function execute() { $resultRedirect = $this->resultRedirectFactory->create(); $data = $this->getRequest()->getParams(); if (isset($data['user_name'])) { $userAcccessIds = ''; if (isset($data['access_data'])) { $userAcccessIds = implode(',', $data['access_data']); } $data['access_data'] = $userAcccessIds; $businessList = $this->businessListFactory->create(); $businessList->setData($data)->save(); $id = $businessList->getId(); $this->coreRegistry->register("entity_id", $id); $this->messageManager->addSuccess("User data has been saved."); return $resultRedirect->setPath('*/*/edit', ['entity_id' => $id]); } else { $this->messageManager->addError( __('Something went wrong while saving the user data.') ); return $resultRedirect->setPath('*/*/edit'); } } }
After this, a ui-select with a search filter using the block method will be displayed on your form.
Change custom type UI select element configuration in Step 4:
Note: Custom field element configuration changed according to the mentioned configuration in getDefaultConfiguration() method of Step 5 file.
$fieldset->addField( 'access_data', //Element Id 'filterselect', //custom type [ 'name' => 'access_data', 'label' => __('Access data'), 'options' => $this->getOptions(), 'multiple' => true, 'required' => true, ] // In array mentioned configuration of element );
Meanwhile Please try the above example and If you have any Queries then please ask in the comment section below.
Thank you!
Be the first to comment.