/   /   /  Magento 2 Backend : Guide to create table (setting) in the system configuration

Note:

For more extensions and themes visit our store

Magento 2 Backend : Guide to create table (setting) in the system configuration


Magento 2 comes with many technique already exist in version 1 but with new way for implementing , one of this flexible tables (grids) in the system configuration.

you can download the project of course from github

We imagine you have  created module , we started from system.xml inside Ibnab/Table/etc/adminhtml/system.xml

1 – Create the field :
for more infos about how working with system.xml plz visit our tutorial :

so we need add this part of code inside system.xml :

  1.  
  2.                 <field id="active" translate="label" sortOrder="220" showInDefault="1" showInWebsite="1" showInStore="0">
  3.                     <label>active buy</label>
  4.                     <frontend_model>Ibnab\Table\Block\System\Config\Form\Field\Active</frontend_model>
  5.                     <backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
  6.                 </field>
  7.  

frontend_model :  block responsible of rendering the columns content of table
backend_model :  it used for saving and loading data from db as serialized format , use can use the standard   Magento\Config\Model\Config\Backend\Serialized\ArraySerialized , or create your own like : Magento\Braintree\Model\System\Config\Backend\Countrycreditcard

2 – Create frontend model :
we need create our class inside Ibnab/Table/Block/System/Form/Field folder , ok here create block Active.php and fill with :

  1. </p>
  2.  
  3. <p><?php
  4. namespace Ibnab\Table\Block\System\Config\Form\Field;
  5. class Active extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray {
  6.     /**
  7.      * Grid columns
  8.      *
  9.      * @var array
  10.      */
  11.     protected $_columns = [];
  12.     protected $_customerGroupRenderer;
  13.     /**
  14.      * Enable the "Add after" button or not
  15.      *
  16.      * @var bool
  17.      */
  18.     protected $_addAfter = true;
  19.      /**
  20.      * Label of add button
  21.      *
  22.      * @var string
  23.      */
  24.     protected $_addButtonLabel;
  25.     /**
  26.      * Check if columns are defined, set template
  27.      *
  28.      * @return void
  29.      */
  30.     protected function _construct() {
  31.         parent::_construct();
  32.         $this->_addButtonLabel = __('Add');
  33.     }
  34.     /**
  35.      * Returns renderer for country element
  36.      *
  37.      * @return \Magento\Braintree\Block\Adminhtml\Form\Field\Countries
  38.      */
  39.     protected function getCustomerGroupRenderer() {
  40.         if (!$this->_customerGroupRenderer) {
  41.             $this->_customerGroupRenderer = $this->getLayout()->createBlock(
  42.                     '\Ibnab\Table\Block\Adminhtml\Form\Field\CustomerGroup', '', ['data' => ['is_render_to_js_template' => true]]
  43.             );
  44.         }
  45.         return $this->_customerGroupRenderer;
  46.     }
  47.     /**
  48.      * Prepare to render
  49.      *
  50.      * @return void
  51.      */
  52.     protected function _prepareToRender() {
  53.         $this->addColumn(
  54.                 'customer_group', [
  55.             'label' => __('Customer Group'),
  56.             'renderer' => $this->getCustomerGroupRenderer(),
  57.                 ]
  58.         );
  59.         $this->addColumn('active', array('label' => __('Active')));
  60.         $this->_addAfter = false;
  61.         $this->_addButtonLabel = __('Add');
  62.     }
  63.     protected function _prepareArrayRow(\Magento\Framework\DataObject $row) {
  64.         $customerGroup = $row->getCustomerGroup();
  65.         $options = [];
  66.         if ($customerGroup) {
  67.             $options['option_' . $this->getCustomerGroupRenderer()->calcOptionHash($customerGroup)] = 'selected="selected"';
  68.         }
  69.         $row->setData('option_extra_attrs', $options);
  70.         }
  71.     /**
  72.      * Render array cell for prototypeJS template
  73.      *
  74.      * @param string $columnName
  75.      * @return string
  76.      * @throws \Exception
  77.      */
  78.     public function renderCellTemplate($columnName)
  79.     {
  80.         if ($columnName == "active") {
  81.             $this->_columns[$columnName]['class'] = 'input-text required-entry validate-number';
  82.             $this->_columns[$columnName]['style'] = 'width:50px';
  83.         }
  84.         return parent::renderCellTemplate($columnName);
  85.     }
  86. }
  87.  

Our class extend the \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray yes we need table field .

We have here many important functions (1 function here need override the parent function for declaring your custom column _prepareToRender()  ):

  1.  
  2.     protected function _prepareToRender() {
  3.         $this->addColumn(
  4.                 'customer_group', [
  5.             'label' => __('Customer Group'),
  6.             'renderer' => $this->getCustomerGroupRenderer(),
  7.                 ]
  8.         );
  9.         $this->addColumn('active', array('label' => __('Active')));
  10.         $this->_addAfter = false;
  11.         $this->_addButtonLabel = __('Add');
  12.     }
  13.  

here we decalre our custom column “input field” the first is select field we related to custom renderer with function getCustomerGroupRenderer() (we back to it)

and the default input text :

  1.  
  2. $this->addColumn('active', array('label' => __('Active')));
  3.  

we use the function of parent :

  1.  
  2.     public function addColumn($name, $params)
  3.     {
  4.         $this->_columns[$name] = [
  5.             'label' => $this->_getParam($params, 'label', 'Column'),
  6.             'size' => $this->_getParam($params, 'size', false),
  7.             'style' => $this->_getParam($params, 'style'),
  8.             'class' => $this->_getParam($params, 'class'),
  9.             'renderer' => false,
  10.         ];
  11.         if (!empty($params['renderer']) && $params['renderer'] instanceof \Magento\Framework\View\Element\AbstractBlock) {
  12.             $this->_columns[$name]['renderer'] = $params['renderer'];
  13.         }
  14.     }
  15.  

the parent function find if have a custom renderer it use , if not it use the default input text field like our case active field .

We back to our renderer for our first column declaration :

  1.  
  2.         $this->addColumn(
  3.                 'customer_group', [
  4.             'label' => __('Customer Group'),
  5.             'renderer' => $this->getCustomerGroupRenderer(),
  6.                 ]
  7.         );
  8.  

the function is :
  1.  
  2.     protected function getCustomerGroupRenderer() {
  3.         if (!$this->_paymentMethodRenderer) {
  4.             $this->_paymentMethodRenderer = $this->getLayout()->createBlock(
  5.                     '\Ibnab\Table\Block\Adminhtml\Form\Field\CustomerGroup', '', ['data' => ['is_render_to_js_template' => true]]
  6.             );
  7.         }
  8.         return $this->_paymentMethodRenderer;
  9.     }
  10.  

Yes we use custom block for showing our field (\Ibnab\Table\Block\Adminhtml\Form\Field\CustomerGroup) the content is :
  1.  
  2. <?php</p>
  3.  
  4. <p>/**
  5.  * Copyright © 2015 Magento. All rights reserved.
  6.  * See COPYING.txt for license details.
  7.  */
  8.  namespace Ibnab\Table\Block\Adminhtml\Form\Field;
  9. class CustomerGroup extends \Magento\Framework\View\Element\Html\Select {
  10.    /**
  11.      * methodList
  12.      *
  13.      * @var array
  14.      */
  15.     protected $groupfactory;
  16.    /**
  17.      * Constructor
  18.      *
  19.      * @param \Magento\Framework\View\Element\Context $context
  20.      * @param \Magento\Braintree\Model\System\Config\Source\Country $countrySource
  21.      * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory
  22.      * @param array $data
  23.      */
  24.     public function __construct(
  25.     \Magento\Framework\View\Element\Context $context, \Magento\Customer\Model\GroupFactory $groupfactory, array $data = []
  26.     ) {
  27.         parent::__construct($context, $data);
  28.         $this->groupfactory = $groupfactory;
  29.     }  
  30.     /**
  31.      * Returns countries array
  32.      *
  33.      * @return array
  34.      */ 
  35.      /**
  36.      * Render block HTML
  37.      *
  38.      * @return string
  39.      */
  40.     public function _toHtml() {
  41.         if (!$this->getOptions()) {
  42.             $customerGroupCollection = $this->groupfactory->create()->getCollection();
  43.             foreach ($customerGroupCollection as $customerGroup) {
  44.                      $this->addOption($customerGroup->getCustomerGroupId(), $customerGroup->getCustomerGroupCode());
  45.             }
  46.         }
  47.         return parent::_toHtml();
  48.     }
  49.     /**
  50.      * Sets name for input element
  51.      *
  52.      * @param string $value
  53.      * @return $this
  54.      */
  55.     public function setInputName($value) {
  56.         return $this->setName($value);
  57.     }
  58. }
  59.  

Our block extend  \Magento\Framework\View\Element\Html\Select , we want select field element ,
in construct we inject the customer group factory and used inside  public function _toHtml() for filled the select input box :

  1.  
  2.     public function _toHtml() {
  3.         if (!$this->getOptions()) {
  4.             $customerGroupCollection = $this->groupfactory->create()->getCollection();
  5.             foreach ($customerGroupCollection as $customerGroup) {
  6.                      $this->addOption($customerGroup->getCustomerGroupId(), $customerGroup->getCustomerGroupCode());
  7.             }
  8.         }
  9.         return parent::_toHtml();
  10.     }
  11.  

re back  to our array table and explore function :

  1.  
  2.     protected function _prepareArrayRow(\Magento\Framework\DataObject $row) {
  3.         $customerGroup = $row->getCustomerGroup();
  4.         $options = [];
  5.         if ($paymentMethod) {
  6.             $options['option_' . $this->getCustomerGroupRenderer()->calcOptionHash($customerGroup)] = 'selected="selected"';
  7.         }
  8.         $row->setData('option_extra_attrs', $options);
  9.         }</p>
  10.  
  11. <p>}
  12.  

we use for select current selected option in our select field element .

3 – Add validation :

you can add validation before save the serialized value , add function :

  1.  
  2.     /**
  3.      * Render array cell for prototypeJS template
  4.      *
  5.      * @param string $columnName
  6.      * @return string
  7.      * @throws \Exception
  8.      */
  9.     public function renderCellTemplate($columnName)
  10.     {
  11.         if ($columnName == "active") {
  12.             $this->_columns[$columnName]['class'] = 'input-text required-entry validate-number';
  13.             $this->_columns[$columnName]['style'] = 'width:50px';
  14.         }
  15.         return parent::renderCellTemplate($columnName);
  16.     }
  17.  

here we validate  the active field is required and number type .

4 – How using the configuration value :
first inject the $scopeConfig inside the class where you want use the configuration :
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig

  1.  
  2. $tableConfig = $this->scopeConfig->getValue('ibnab_activebuy_config/general/active', ScopeConfigInterface::SCOPE_TYPE_DEFAULT);
  3. if ($tableConfig) :
  4.     $tableConfigResults = unserialize($tableConfig);
  5.     if (is_array($tableConfigResults)) {
  6.         foreach($tableConfigResults as $tableConfigResult) {
  7.             $customer_group = $tableConfigResult['customer_group'];
  8.             $active = $tableConfigResult['active'];
  9.         }
  10.     endif;
  11. }
  12.  

that is all

Comments

Related Posts

make your store more efficient

Solving problems. With open source technology. Professional results. That’s what makes Ibnab your best choice

IBNAB is a company made of a group of professionals whose work is providing secure open source solutions. Our company strives for reaching magnificent results with each experience and provides professional open source solutions that cover every part of the business process.