The Development Steps for Conventional Admin Form | Grid | Store Filter in Magento 2

The Development Steps for Conventional Admin Form | Grid | Store Filter in Magento 2
COMMENTS ()
Tweet

 

 

The learning curve for Magento 2, with all of the updates, has become even steeper. In this blog, I plan to showcase you how to develop admin form and grid in Magento 2.

Magento 2 provides two ways for development of admin form and grid.

1)   UI Component (New Approach).

2)   Conventional Approach (similar with Magento-1).

I have already blogged on “UI Component” approach link. In this blog, I will cover the second” Conventional” approach.

The most critical part in both approaches is appending of store-field and filter under admin form and grid. The reason for writing this blog, is to simplify the appending process of store-field and filter, by highlighting the necessary development steps.

The “Conventional” module development will be divided into 2 parts.

  • The 1st part will cover the admin form and grid without store field and filter.
  • The 2nd part will cover the addition of store-field and filter under admin grid and form.

For complete “conventional” approach, module overview and structure, I have provided multiple screen-shots:

SCREEN-SHOTS:

Magento 2 Blog folio3 - conventional approach for store grid filter

Magento 2 Blog folio3 - conventional approach for store grid filter

Magento 2 Blog folio3 - conventional approach for store grid filter

Magento 2 Blog folio3 - conventional approach for store grid filter

PART-1: 

MODULE STRUCTURE & DEVELOPMENT

(without store field & filter)

Step-1:

Create module required files and folder:

app/code/Folo3/ConventionalFormGridStoreFilter/registration.php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Folio3_ConventionalFormGridStoreFilter',
    __DIR__
);

app/code/Folo3/ConventionalFormGridStoreFilter/etc/module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Folio3_ConventionalFormGridStoreFilter" setup_version="1.0.0" />
</config>

 

Step-2:

Define admin menu configurations with necessary routes:

app/code/Folo3/ConventionalFormGridStoreFilter/etc/adminhtml/menu.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter" title="Folio3" module="Folio3_ConventionalFormGridStoreFilter" sortOrder="30" resource="Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter"/>
        <add id="Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_manage" title="Form" module="Folio3_ConventionalFormGridStoreFilter" sortOrder="10" parent="Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter" action="conventionalformgridstorefilter/index/" resource="Folio3_ConventionalFormGridStoreFilter::manage"/>
    </menu>
</config>

app/code/Folo3/ConventionalFormGridStoreFilter/etc/adminhtml/routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="conventionalformgridstorefilter" frontName="conventionalformgridstorefilter">
            <module name="Folio3_ConventionalFormGridStoreFilter" />
        </route>
    </router>
</config>

 

Step-3:

Write installer script that will create DB table “folio3_conventionalformgridstorefilter”:

app/code/Folo3/ConventionalFormGridStoreFilter/Setup/InstallSchema.php

namespace Folio3\ConventionalFormGridStoreFilter\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
		$installer = $setup;
		$installer->startSetup();

		/**
		 * Creating table folio3_conventionalformgridstorefilter
		 */
		$table = $installer->getConnection()->newTable(
			$installer->getTable('folio3_conventionalformgridstorefilter')
		)->addColumn(
			'conventionalformgridstorefilter_id',
			\Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
			null,
			['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
			'Entity Id'
		)->addColumn(
			'title',
			\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
			255,
			['nullable' => true],
			'News Title'
		)->addColumn(
			'author',
			\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
			255,
			['nullable' => true,'default' => null],
			'Author'
		)->addColumn(
			'content',
			\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
			'2M',
			['nullable' => true,'default' => null],
			'Content'
		)->addColumn(
			'image',
			\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
			null,
			['nullable' => true,'default' => null],
			'ConventionalFormGridStoreFilter image media path'
		)->addColumn(
			'created_at',
			\Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
			null,
			['nullable' => false],
			'Created At'
		)->addColumn(
			'published_at',
			\Magento\Framework\DB\Ddl\Table::TYPE_DATE,
			null,
			['nullable' => true,'default' => null],
			'publish date'
		)->setComment(
			'ConventionalFormGridStoreFilter item'
		);
		$installer->getConnection()->createTable($table);
		$installer->endSetup();
	}
}

 

Note:

From next steps we will cover (admin) MVC (module-view-contoller) part of the module.

Step-4:

Create (admin) required view XML files.

app/code/Folo3/ConventionalFormGridStoreFilter/view/adminhtml/layout/conventionalformgridstorefilter_index_edit.xml

<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="editor"/>
    <body>
        <referenceContainer name="content">
            <block class="Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit" name="conventionalformgridstorefilter_edit"/>
        </referenceContainer>
        <referenceContainer name="left">
            <block class="Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit\Tabs" name="conventionalformgridstorefilter_edit_tabs">
                <block class="Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit\Tab\Main" name="conventionalformgridstorefilter_edit_tab_main"/>             
                <action method="addTab">
                    <argument name="name" xsi:type="string">main_section</argument>
                    <argument name="block" xsi:type="string">conventionalformgridstorefilter_edit_tab_main</argument>
                </action>
            </block>
        </referenceContainer>
    </body>
</page>

app/code/Folo3/ConventionalFormGridStoreFilter/view/adminhtml/layout/conventionalformgridstorefilter_index_grid.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="formkey"/>
    <container name="root" label="Root">
        <block class="Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Grid" name="admin.conventionalformgridstorefilter.grid"/>
    </container>
</page>

app/code/Folo3/ConventionalFormGridStoreFilter/view/adminhtml/layout/conventionalformgridstorefilter_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter" name="admin.conventionalformgridstorefilter.grid"/>
        </referenceContainer>
    </body>
</page>

app/code/Folo3/ConventionalFormGridStoreFilter/view/adminhtml/layout/conventionalformgridstorefilter_index_new.xml

<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="conventionalformgridstorefilter_index_edit"/>

   <body/>

</page>

 

Step-5:

Create (admin) required view BLOCK files.

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml;

class ConventionalFormGridStoreFilter extends \Magento\Backend\Block\Widget\Grid\Container
{
    /**
     * Constructor
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_controller = 'adminhtml_ConventionalFormGridStoreFilter';
        $this->_blockGroup = 'Folio3_ConventionalFormGridStoreFilter';
        $this->_headerText = __('Folio3 Form');
        $this->_addButtonLabel = __('Add New Form');
        parent::_construct();
        if ($this->_isAllowedAction('Folio3_ConventionalFormGridStoreFilter::save')) {
            $this->buttonList->update('add', 'label', __('Add New Form'));
        } else {
            $this->buttonList->remove('add');
        }
    }
    
    /**
     * Check permission for passed action
     *
     * @param string $resourceId
     * @return bool
     */
    protected function _isAllowedAction($resourceId)
    {
        return $this->_authorization->isAllowed($resourceId);
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Edit.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter;

/**
 * Admin ConventionalFormGridStoreFilter page
 *
 */
class Edit extends \Magento\Backend\Block\Widget\Form\Container
{
    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;

    /**
     * @param \Magento\Backend\Block\Widget\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Widget\Context $context,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        $this->_coreRegistry = $registry;
        parent::__construct($context, $data);
    }

    /**
     * Initialize cms page edit block
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_objectId = 'conventionalformgridstorefilter_id';
        $this->_blockGroup = 'Folio3_ConventionalFormGridStoreFilter';
        $this->_controller = 'adminhtml_ConventionalFormGridStoreFilter';

        parent::_construct();

        if ($this->_isAllowedAction('Folio3_ConventionalFormGridStoreFilter::save')) {
            $this->buttonList->update('save', 'label', __('Save Form'));
            $this->buttonList->add(
                'saveandcontinue',
                [
                    'label' => __('Save and Continue Edit'),
                    'class' => 'save',
                    'data_attribute' => [
                        'mage-init' => [
                            'button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form'],
                        ],
                    ]
                ],
                -100
            );
        } else {
            $this->buttonList->remove('save');
        }

        if ($this->_isAllowedAction('Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_delete')) {
            $this->buttonList->update('delete', 'label', __('Delete Form'));
        } else {
            $this->buttonList->remove('delete');
        }
    }

    /**
     * Retrieve text for header element depending on loaded page
     *
     * @return string
     */
    public function getHeaderText()
    {
        if ($this->_coreRegistry->registry('conventionalformgridstorefilter')->getId()) {
            return __("Edit Form '%1'", $this->escapeHtml($this->_coreRegistry->registry('conventionalformgridstorefilter')->getTitle()));
        } else {
            return __('New Form');
        }
    }

    /**
     * Check permission for passed action
     *
     * @param string $resourceId
     * @return bool
     */
    protected function _isAllowedAction($resourceId)
    {
        return $this->_authorization->isAllowed($resourceId);
    }

    /**
     * Getter of url for "Save and Continue" button
     * tab_id will be replaced by desired by JS later
     *
     * @return string
     */
    protected function _getSaveAndContinueUrl()
    {
        return $this->getUrl('conventionalformgridstorefilter/*/save', ['_current' => true, 'back' => 'edit', 'active_tab' => '{{tab_id}}']);
    }

    /**
     * Prepare layout
     *
     * @return \Magento\Framework\View\Element\AbstractBlock
     */
    protected function _prepareLayout()
    {
        $this->_formScripts[] = "
            function toggleEditor() {
                if (tinyMCE.getInstanceById('page_content') == null) {
                    tinyMCE.execCommand('mceAddControl', false, 'page_content');
                } else {
                    tinyMCE.execCommand('mceRemoveControl', false, 'page_content');
                }
            };
        ";
        return parent::_prepareLayout();
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Grid.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter;

/**
 * Adminhtml ConventionalFormGridStoreFilter grid
 */
class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
{
    /**
     * @var \Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter\CollectionFactory
     */
    protected $_collectionFactory;

    /**
     * @var \Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter
     */
    protected $_conventionalformgridstorefilter;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Backend\Helper\Data $backendHelper
     * @param \Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter $conventionalformgridstorefilterPage
     * @param \Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter\CollectionFactory $collectionFactory
     * @param \Magento\Core\Model\PageLayout\Config\Builder $pageLayoutBuilder
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Backend\Helper\Data $backendHelper,
        \Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter $conventionalformgridstorefilter,
        \Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter\CollectionFactory $collectionFactory,
        array $data = []
    ) {
        $this->_collectionFactory = $collectionFactory;
        $this->_conventionalformgridstorefilter = $conventionalformgridstorefilter;
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('conventionalformgridstorefilterGrid');
        $this->setDefaultSort('conventionalformgridstorefilter_id');
        $this->setDefaultDir('DESC');
        $this->setUseAjax(true);
        $this->setSaveParametersInSession(true);
    }

    /**
     * Prepare collection
     *
     * @return \Magento\Backend\Block\Widget\Grid
     */
    protected function _prepareCollection()
    {
        $collection = $this->_collectionFactory->create();
        /* @var $collection \Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter\Collection */
        $this->setCollection($collection);

        return parent::_prepareCollection();
    }

    /**
     * Prepare columns
     *
     * @return \Magento\Backend\Block\Widget\Grid\Extended
     */
    protected function _prepareColumns()
    {
        $this->addColumn('conventionalformgridstorefilter_id', [
            'header'    => __('ID'),
            'index'     => 'conventionalformgridstorefilter_id',
        ]);
        
        $this->addColumn('title', ['header' => __('Title'), 'index' => 'title']);
        $this->addColumn('author', ['header' => __('Author'), 'index' => 'author']);
        
        $this->addColumn(
            'published_at',
            [
                'header' => __('Published On'),
                'index' => 'published_at',
                'type' => 'date',
                'header_css_class' => 'col-date',
                'column_css_class' => 'col-date'
            ]
        );
        
        $this->addColumn(
            'created_at',
            [
                'header' => __('Created'),
                'index' => 'created_at',
                'type' => 'datetime',
                'header_css_class' => 'col-date',
                'column_css_class' => 'col-date'
            ]
        );
        
        $this->addColumn(
            'action',
            [
                'header' => __('Edit'),
                'type' => 'action',
                'getter' => 'getId',
                'actions' => [
                    [
                        'caption' => __('Edit'),
                        'url' => [
                            'base' => '*/*/edit',
                            'params' => ['store' => $this->getRequest()->getParam('store')]
                        ],
                        'field' => 'conventionalformgridstorefilter_id'
                    ]
                ],
                'sortable' => false,
                'filter' => false,
                'header_css_class' => 'col-action',
                'column_css_class' => 'col-action'
            ]
        );

        return parent::_prepareColumns();
    }

    /**
     * Row click url
     *
     * @param \Magento\Framework\Object $row
     * @return string
     */
    public function getRowUrl($row)
    {
        return $this->getUrl('*/*/edit', ['conventionalformgridstorefilter_id' => $row->getId()]);
    }

    /**
     * Get grid url
     *
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl('*/*/grid', ['_current' => true]);
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Edit/Form.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit;

/**
 * Adminhtml conventionalformgridstorefilter edit form block
 *
 */
class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
    /**
     * Prepare form
     *
     * @return $this
     */
    protected function _prepareForm()
    {
        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create(
            ['data' => ['id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post','enctype' => 'multipart/form-data']]
        );
        $form->setUseContainer(true);
        $this->setForm($form);
        return parent::_prepareForm();
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Edit/Tabs.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit;

/**
 * Admin conventionalformgridstorefilter left menu
 */
class Tabs extends \Magento\Backend\Block\Widget\Tabs
{
    /**
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('page_tabs');
        $this->setDestElementId('edit_form');
        $this->setTitle(__('Folio3'));
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Edit/Tab/Main.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\ConventionalFormGridStoreFilter\Edit\Tab;

/**
 * Cms page edit form main tab
 */
class Main extends \Magento\Backend\Block\Widget\Form\Generic implements \Magento\Backend\Block\Widget\Tab\TabInterface
{
    /**
     * @var \Magento\Store\Model\System\Store
     */
    protected $_systemStore;
    protected $wysiwygConfig;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param \Magento\Store\Model\System\Store $systemStore
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Store\Model\System\Store $systemStore,
        \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig,
        array $data = []
    ) {
        $this->_systemStore = $systemStore;
        $this->wysiwygConfig = $wysiwygConfig;
        parent::__construct($context, $registry, $formFactory, $data);
    }

    /**
     * Prepare form
     *
     * @return $this
     */
    protected function _prepareForm()
    {
        /* @var $model \Magento\Cms\Model\Page */
        $model = $this->_coreRegistry->registry('conventionalformgridstorefilter');

        /*
         * Checking if user have permissions to save information
         */
        if ($this->_isAllowedAction('Folio3_ConventionalFormGridStoreFilter::save')) {
            $isElementDisabled = false;
        } else {
            $isElementDisabled = true;
        }

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create();

        $form->setHtmlIdPrefix('conventionalformgridstorefilter_main_');

        $fieldset = $form->addFieldset('base_fieldset', ['legend' => __('Form Information')]);

        if ($model->getId()) {
            $fieldset->addField('conventionalformgridstorefilter_id', 'hidden', ['name' => 'conventionalformgridstorefilter_id']);
        }

        $fieldset->addField(
            'title',
            'text',
            [
                'name' => 'title',
                'label' => __('Form Title'),
                'title' => __('Form Title'),
                'required' => true,
                'disabled' => $isElementDisabled
            ]
        );

        $fieldset->addField(
            'author',
            'text',
            [
                'name' => 'author',
                'label' => __('Author'),
                'title' => __('Author'),
                'required' => true,
                'disabled' => $isElementDisabled
            ]
        );
        
        $dateFormat = $this->_localeDate->getDateFormat(\IntlDateFormatter::SHORT);
        $fieldset->addField('published_at', 'date', [
            'name'     => 'published_at',
            'date_format' => $dateFormat,
            'image'    => '',//$this->getViewFileUrl('images/grid-cal.gif'),
            'value' => $model->getPublishedAt(),
            'label'    => __('Publishing Date'),
            'title'    => __('Publishing Date'),
            'required' => true
        ]);
        
        $layoutFieldset = $form->addFieldset(
            'image_fieldset',
            ['legend' => __('Image Thumbnail'), 'class' => 'fieldset-wide', 'disabled' => $isElementDisabled]
        );

        $layoutFieldset->addField(
            'image',
            'image',
            [
                'name' => 'image',
                'label' => __('Image'),
                'title' => __('Image'),
                'required'  => false,
                'disabled' => $isElementDisabled
            ]
        );
        
        $fieldset = $form->addFieldset(
            'content_fieldset',
            ['legend' => __('Content'), 'class' => 'fieldset-wide']
        );

        $wysiwygConfig = $this->wysiwygConfig->getConfig(['tab_id' => $this->getTabId()]);

        $contentField = $fieldset->addField(
            'content',
            'editor',
            [
                'name' => 'content',
                'style' => 'height:36em;',
                'required' => true,
                'disabled' => $isElementDisabled,
                'config' => $wysiwygConfig
            ]
        );

        // Setting custom renderer for content field to remove label column
        $renderer = $this->getLayout()->createBlock(
            'Magento\Backend\Block\Widget\Form\Renderer\Fieldset\Element'
        )->setTemplate(
            'Magento_Cms::page/edit/form/renderer/content.phtml'
        );
        $contentField->setRenderer($renderer);

        $this->_eventManager->dispatch('adminhtml_conventionalformgridstorefilter_edit_tab_main_prepare_form', ['form' => $form]);

        $form->setValues($model->getData());
        $this->setForm($form);

        return parent::_prepareForm();
    }

    /**
     * Prepare label for tab
     *
     * @return string
     */
    public function getTabLabel()
    {
        return __('Form Information');
    }

    /**
     * Prepare title for tab
     *
     * @return string
     */
    public function getTabTitle()
    {
        return __('Form Information');
    }

    /**
     * {@inheritdoc}
     */
    public function canShowTab()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function isHidden()
    {
        return false;
    }

    /**
     * Check permission for passed action
     *
     * @param string $resourceId
     * @return bool
     */
    protected function _isAllowedAction($resourceId)
    {
        return $this->_authorization->isAllowed($resourceId);
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/Form/Element/Image.php

namespace Folio3\ConventionalFormGridStoreFilter\Block\Adminhtml\Form\Element;

class Image extends \Magento\Framework\Data\Form\Element\Image
{ 
    /**
     * Get image preview url
     *
     * @return string
     */
    protected function _getUrl()
    {
        return $this->getValue();
    }
}

 

Step-6:

Create MODEL files required for CRUD operations.

app/code/Folo3/ConventionalFormGridStoreFilter/Model/ConventionalFormGridStoreFilter.php

namespace Folio3\ConventionalFormGridStoreFilter\Model;

/**
 * ConventionalFormGridStoreFilter Model
 *
 * @method \Folio3\ConventionalFormGridStoreFilter\Model\Resource\Page getResource()
 */
class ConventionalFormGridStoreFilter extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter');
    }

}

app/code/Folo3/ConventionalFormGridStoreFilter/Model/ResourceModel/ConventionalFormGridStoreFilter.php

namespace Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel;

/**
 * ConventionalFormGridStoreFilter Resource Model
 */
class ConventionalFormGridStoreFilter extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('folio3_conventionalformgridstorefilter', 'conventionalformgridstorefilter_id');
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Model/ResourceModel/ConventionalFormGridStoreFilter/Collection.php

namespace Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * Resource initialization
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter', 'Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter');
    }
}

 

Step-7:

Create CONTROLLER file(s) required for routing and requests processing.

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Delete.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

class Delete extends \Magento\Backend\App\Action
{
    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_delete');
    }

    /**
     * Delete action
     *
     * @return void
     */
    public function execute()
    {
        // check if we know what should be deleted
        $id = $this->getRequest()->getParam('conventionalformgridstorefilter_id');
		/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        if ($id) {
            $title = "";
            try {
                // init model and delete
                $model = $this->_objectManager->create('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter');
                $model->load($id);
                $title = $model->getTitle();
                $model->delete();
                // display success message
                $this->messageManager->addSuccess(__('The data has been deleted.'));
                // go to grid
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                // display error message
                $this->messageManager->addError($e->getMessage());
                // go back to edit form
                return $resultRedirect->setPath('*/*/edit', ['page_id' => $id]);
            }
        }
        // display error message
        $this->messageManager->addError(__('We can\'t find a data to delete.'));
        // go to grid
        return $resultRedirect->setPath('*/*/');
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Edit.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

class Edit extends \Magento\Backend\App\Action
{
    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;
	
	/**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param Action\Context $context
	 * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Magento\Framework\Registry $registry
     */
    public function __construct(Action\Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Framework\Registry $registry)
    {
        $this->resultPageFactory = $resultPageFactory;
		$this->_coreRegistry = $registry;
        parent::__construct($context);
    }

    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Folio3_ConventionalFormGridStoreFilter::save');
    }

    /**
     * Init actions
     *
     * @return $this
     */
    protected function _initAction()
    {
        // load layout, set active menu and breadcrumbs
        /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $resultPage->setActiveMenu(
            'Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_manage'
        )->addBreadcrumb(
            __('ConventionalFormGridStoreFilter'),
            __('ConventionalFormGridStoreFilter')
        )->addBreadcrumb(
            __('Manage Form'),
            __('Manage Form')
        );
        return $resultPage;
    }

    /**
     * Edit CMS page
     *
     * @return void
     */
    public function execute()
    {
        // 1. Get ID and create model
        $id = $this->getRequest()->getParam('conventionalformgridstorefilter_id');
        $model = $this->_objectManager->create('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter');

        // 2. Initial checking
        if ($id) {
            $model->load($id);
            if (!$model->getId()) {
                $this->messageManager->addError(__('This form no longer exists.'));
				/** \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
                $resultRedirect = $this->resultRedirectFactory->create();
                return $resultRedirect->setPath('*/*/');
            }
        }

        // 3. Set entered data if was error when we do save
        $data = $this->_objectManager->get('Magento\Backend\Model\Session')->getFormData(true);
        if (!empty($data)) {
            $model->setData($data);
        }

        // 4. Register model to use later in blocks
        $this->_coreRegistry->register('conventionalformgridstorefilter', $model);

        // 5. Build edit form
		/** @var \Magento\Backend\Model\View\Result\Page $resultPage */
        $resultPage = $this->_initAction();
        $resultPage->addBreadcrumb(
            $id ? __('Edit Form') : __('New Form'),
            $id ? __('Edit Form') : __('New Form')
        );
        $resultPage->getConfig()->getTitle()->prepend(__('Folio3 Form'));
        $resultPage->getConfig()->getTitle()
            ->prepend($model->getId() ? $model->getTitle() : __('New Form'));
        return $resultPage;
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Grid.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

class Grid extends \Magento\Customer\Controller\Adminhtml\Index
{
    /**
     * Customer grid action
     *
     * @return void
     */
    public function execute()
    {
        $this->_view->loadLayout(false);
        $this->_view->renderLayout();
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Index.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Index extends \Magento\Backend\App\Action
{
	/**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param Context $context
     * @param PageFactory $resultPageFactory
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
    }
	
    /**
     * Check the permission to run it
     *
     * @return bool
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_manage');
    }

    /**
     * ConventionalFormGridStoreFilter List action
     *
     * @return void
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $resultPage->setActiveMenu(
            'Folio3_ConventionalFormGridStoreFilter::conventionalformgridstorefilter_manage'
        )->addBreadcrumb(
            __('ConventionalFormGridStoreFilter'),
            __('ConventionalFormGridStoreFilter')
        )->addBreadcrumb(
            __('Manage Form'),
            __('Manage Form')
        );
        $resultPage->getConfig()->getTitle()->prepend(__('Folio3 Form'));
        return $resultPage;
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/NewAction.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

class NewAction extends \Magento\Backend\App\Action
{
	/**
     * @var \Magento\Backend\Model\View\Result\Forward
     */
    protected $resultForwardFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
    ) {
        $this->resultForwardFactory = $resultForwardFactory;
        parent::__construct($context);
    }
	
    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Folio3_ConventionalFormGridStoreFilter::save');
    }

    /**
     * Forward to edit
     *
     * @return void
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Forward $resultForward */
        $resultForward = $this->resultForwardFactory->create();
        return $resultForward->forward('edit');
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/PostDataProcessor.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

class PostDataProcessor
{
    /**
     * @var \Magento\Framework\Stdlib\DateTime\Filter\Date
     */
    protected $dateFilter;

    /**
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $messageManager;

    /**
     * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Core\Model\Layout\Update\ValidatorFactory $validatorFactory
     */
    public function __construct(
        \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
        \Magento\Framework\Message\ManagerInterface $messageManager
    ) {
        $this->dateFilter = $dateFilter;
        $this->messageManager = $messageManager;
    }

    /**
     * Filtering posted data. Converting localized data if needed
     *
     * @param array $data
     * @return array
     */
    public function filter($data)
    {
        $inputFilter = new \Zend_Filter_Input(
            ['published_at' => $this->dateFilter],
            [],
            $data
        );
        $data = $inputFilter->getUnescaped();
        return $data;
    }

    /**
     * Validate post data
     *
     * @param array $data
     * @return bool     Return FALSE if someone item is invalid
     */
    public function validate($data)
    {
        $errorNo = true;
        return $errorNo;
    }
}

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Save.php

namespace Folio3\ConventionalFormGridStoreFilter\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

class Save extends \Magento\Backend\App\Action
{
    /**
     * @var PostDataProcessor
     */
    protected $dataProcessor;

    /**
     * @param Action\Context $context
     * @param PostDataProcessor $dataProcessor
     */
    public function __construct(Action\Context $context, PostDataProcessor $dataProcessor)
    {
        $this->dataProcessor = $dataProcessor;
        parent::__construct($context);
    }

    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Folio3_ConventionalFormGridStoreFilter::save');
    }

    /**
     * Save action
     *
     * @return void
     */
    public function execute()
    {
        $data = $this->getRequest()->getPostValue();
        if ($data) {
            $data = $this->dataProcessor->filter($data);
            $model = $this->_objectManager->create('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter');

            $id = $this->getRequest()->getParam('conventionalformgridstorefilter_id');
            if ($id) {
                $model->load($id);
            }
            
            // save image data and remove from data array
            if (isset($data['image'])) {
                $imageData = $data['image'];
                unset($data['image']);
            } else {
                $imageData = array();
            }

            $model->addData($data);

            if (!$this->dataProcessor->validate($data)) {
                $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $model->getId(), '_current' => true]);
                return;
            }

            try {
                $imageHelper = $this->_objectManager->get('Folio3\ConventionalFormGridStoreFilter\Helper\Data');

                if (isset($imageData['delete']) && $model->getImage()) {
                    $imageHelper->removeImage($model->getImage());
                    $model->setImage(null);
                }
                
                $imageFile = $imageHelper->uploadImage('image');
                //print_r($imageFile);
                if ($imageFile) {
                    $model->setImage('ConventionalFormGridStoreFilter/'.$imageFile);
                }

                $model->save();
                $this->messageManager->addSuccess(__('The Data has been saved.'));
                $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false);
                if ($this->getRequest()->getParam('back')) {
                    $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $model->getId(), '_current' => true]);
                    return;
                }
                $this->_redirect('*/*/');
                return;
            } catch (\Magento\Framework\Model\Exception $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\RuntimeException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\Exception $e) {
                $this->messageManager->addException($e, __('Something went wrong while saving the data.'));
            }

            $this->_getSession()->setFormData($data);
            $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $this->getRequest()->getParam('conventionalformgridstorefilter_id')]);
            return;
        }
        $this->_redirect('*/*/');
    }
}

 

Step-8:

Create HELPER file for accessing friendly methods, like image resizing etc.

app/code/Folo3/ConventionalFormGridStoreFilter/Helper/Data.php

namespace Folio3\ConventionalFormGridStoreFilter\Helper;

use Magento\Framework\App\Filesystem\DirectoryList;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * Path to store config where count of conventionalformgridstorefilter posts per page is stored
     *
     * @var string
     */
    const XML_PATH_ITEMS_PER_PAGE     = 'conventionalformgridstorefilter/view/items_per_page';
    
    /**
     * Media path to extension images
     *
     * @var string
     */
    const MEDIA_PATH    = 'ConventionalFormGridStoreFilter';

    /**
     * Maximum size for image in bytes
     * Default value is 1M
     *
     * @var int
     */
    const MAX_FILE_SIZE = 1048576;

    /**
     * Manimum image height in pixels
     *
     * @var int
     */
    const MIN_HEIGHT = 50;

    /**
     * Maximum image height in pixels
     *
     * @var int
     */
    const MAX_HEIGHT = 800;

    /**
     * Manimum image width in pixels
     *
     * @var int
     */
    const MIN_WIDTH = 50;

    /**
     * Maximum image width in pixels
     *
     * @var int
     */
    const MAX_WIDTH = 1024;

    /**
     * Array of image size limitation
     *
     * @var array
     */
    protected $_imageSize   = array(
        'minheight'     => self::MIN_HEIGHT,
        'minwidth'      => self::MIN_WIDTH,
        'maxheight'     => self::MAX_HEIGHT,
        'maxwidth'      => self::MAX_WIDTH,
    );
    
    /**
     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
     */
    protected $mediaDirectory;

    /**
     * @var \Magento\Framework\Filesystem
     */
    protected $filesystem;

    /**
     * @var \Magento\Framework\HTTP\Adapter\FileTransferFactory
     */
    protected $httpFactory;
    
    /**
     * File Uploader factory
     *
     * @var \Magento\Core\Model\File\UploaderFactory
     */
    protected $_fileUploaderFactory;
    
    /**
     * File Uploader factory
     *
     * @var \Magento\Framework\Io\File
     */
    protected $_ioFile;
    
    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;
    
    /**
     * @param \Magento\Framework\App\Helper\Context $context
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Framework\File\Size $fileSize,
        \Magento\Framework\HTTP\Adapter\FileTransferFactory $httpFactory,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Framework\Filesystem\Io\File $ioFile,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Image\Factory $imageFactory
    ) {
        $this->_scopeConfig = $scopeConfig;
        $this->filesystem = $filesystem;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        $this->httpFactory = $httpFactory;
        $this->_fileUploaderFactory = $fileUploaderFactory;
        $this->_ioFile = $ioFile;
        $this->_storeManager = $storeManager;
        $this->_imageFactory = $imageFactory;
        parent::__construct($context);
    }
    
    /**
     * Remove ConventionalFormGridStoreFilter item image by image filename
     *
     * @param string $imageFile
     * @return bool
     */
    public function removeImage($imageFile)
    {
        $io = $this->_ioFile;
        $io->open(array('path' => $this->getBaseDir()));
        if ($io->fileExists($imageFile)) {
            return $io->rm($imageFile);
        }
        return false;
    }
    
    /**
     * Return URL for resized ConventionalFormGridStoreFilter Item Image
     *
     * @param Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter $item
     * @param integer $width
     * @param integer $height
     * @return bool|string
     */
    public function resize(\Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter $item, $width, $height = null)
    {
        if (!$item->getImage()) {
            return false;
        }

        if ($width < self::MIN_WIDTH || $width > self::MAX_WIDTH) {
            return false;
        }
        $width = (int)$width;

        if (!is_null($height)) {
            if ($height < self::MIN_HEIGHT || $height > self::MAX_HEIGHT) {
                return false;
            }
            $height = (int)$height;
        }

        $imageFile = $item->getImage();
        $cacheDir  = $this->getBaseDir() . '/' . 'cache' . '/' . $width;
        $cacheUrl  = $this->getBaseUrl() . '/' . 'cache' . '/' . $width . '/';

        $io = $this->_ioFile;
        $io->checkAndCreateFolder($cacheDir);
        $io->open(array('path' => $cacheDir));
        if ($io->fileExists($imageFile)) {
            return $cacheUrl . $imageFile;
        }

        try {
            $image = $this->_imageFactory->create($this->getBaseDir() . '/' . $imageFile);
            $image->resize($width, $height);
            $image->save($cacheDir . '/' . $imageFile);
            return $cacheUrl . $imageFile;
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * Upload image and return uploaded image file name or false
     *
     * @throws Mage_Core_Exception
     * @param string $scope the request key for file
     * @return bool|string
     */
    public function uploadImage($scope)
    {
        $adapter = $this->httpFactory->create();
        $adapter->addValidator(new \Zend_Validate_File_ImageSize($this->_imageSize));
        $adapter->addValidator(
            new \Zend_Validate_File_FilesSize(['max' => self::MAX_FILE_SIZE])
        );
        
        if ($adapter->isUploaded($scope)) {
            // validate image
            if (!$adapter->isValid($scope)) {
                throw new \Exception(__('Uploaded image is not valid.'));
            }
            
            $uploader = $this->_fileUploaderFactory->create(['fileId' => $scope]);
            $uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png']);
            $uploader->setAllowRenameFiles(true);
            $uploader->setFilesDispersion(false);
            $uploader->setAllowCreateFolders(true);
            
            if ($uploader->save($this->getBaseDir())) {
                return $uploader->getUploadedFileName();
            }
        }
        return false;
    }
    
    /**
     * Return the base media directory for ConventionalFormGridStoreFilter Item images
     *
     * @return string
     */
    public function getBaseDir()
    {
        $path = $this->filesystem->getDirectoryRead(
            DirectoryList::MEDIA
        )->getAbsolutePath(self::MEDIA_PATH);
        return $path;
    }
    
    /**
     * Return the Base URL for ConventionalFormGridStoreFilter Item images
     *
     * @return string
     */
    public function getBaseUrl()
    { 
        return $this->_storeManager->getStore()->getBaseUrl(
                \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
            ) . '/' . self::MEDIA_PATH;
    }
    
    /**
     * Return the number of items per page
     * @return int
     */
    public function getConventionalFormGridStoreFilterPerPage()
    {
        return abs((int)$this->_scopeConfig->getValue(self::XML_PATH_ITEMS_PER_PAGE, \Magento\Store\Model\ScopeInterface::SCOPE_STORE));
    }
}


 

 

PART-2:

MODULE STRUCTURE & DEVELOPMENT

(with store field & filter)

First we will show how to append store-field under form then will render under GRID with filter work.

Step-1:

Add new table “folio3_conventionalformgridstorefilter_store”, by upgradeschema script:

app/code/Folo3/ConventionalFormGridStoreFilter/Setup/UpgradeSchema.php

namespace Folio3\ConventionalFormGridStoreFilter\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class UpgradeSchema implements UpgradeSchemaInterface
{

    /**
     * {@inheritdoc}
     */
    public function upgrade(
        SchemaSetupInterface $setup,
        ModuleContextInterface $context
    ) {
        $setup->startSetup();
        if (version_compare($context->getVersion(), "1.0.1", "<")) {
            /**
             * Create table 'folio3_conventionalformgridstorefilter_store'
             */
            $table = $setup->getConnection()->newTable(
                $setup->getTable('folio3_conventionalformgridstorefilter_store')
            )->addColumn(
                'conventionalformgridstorefilter_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned' => true, 'nullable' => false, 'primary' => true],
                'Entity ID'
            )->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned' => true, 'nullable' => false, 'primary' => true],
                'Store ID'
            )
            ->addIndex(
                $setup->getIdxName('folio3_conventionalformgridstorefilter_store', ['store_id']),
                ['store_id']
            )
            ->addForeignKey(
                $setup->getFkName('folio3_conventionalformgridstorefilter_store', 'conventionalformgridstorefilter_id', 'folio3_conventionalformgridstorefilter', 'conventionalformgridstorefilter_id'),
                'conventionalformgridstorefilter_id',
                $setup->getTable('folio3_conventionalformgridstorefilter'),
                'conventionalformgridstorefilter_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName('folio3_conventionalformgridstorefilter_store', 'store_id', 'store', 'store_id'),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment(
                'Folio3 Conventional Form Grid Store Filter Store Linkage Table'
            );
            
            $setup->getConnection()->createTable($table);
        }
        
        $setup->endSetup();
    }
}

 

Step-2:

Update module version, to run (above) upgrade script.

app/code/Folo3/ConventionalFormGridStoreFilter/etc/module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Folio3_ConventionalFormGridStoreFilter" setup_version="1.0.1" />
</config>

 

Step-3:

In order to show store-field under form, insert following code by editing the following file:

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/ConventionalFormGridStoreFilter/Edit/Tab/Main.php

$field = $fieldset->addField(
            'select_stores',
            'multiselect',
            [
                'label' => __('Visibility'),
                'required' => false,
                'name' => 'stores[]',
                'values' => $this->_systemStore->getStoreValuesForForm()
            ]
        );
        $renderer = $this->getLayout()->createBlock(
            \Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset\Element::class
        );
        $field->setRenderer($renderer);
        $model→setSelectStores($model→getStores());

 

Step-4:

Store field CRUD operation(s) can be code by editing the following MODEL and CONTROLLER file(s):

app/code/Folo3/ConventionalFormGridStoreFilter/Model/ResourceModel/ConventionalFormGridStoreFilter.php

namespace Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel;

use Magento\Framework\Model\AbstractModel;

/**
 * ConventionalFormGridStoreFilter Resource Model
 */
class ConventionalFormGridStoreFilter extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{

    /**
     * Core model store manager interface
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param string $connectionName
     */
    public function __construct(
        \Magento\Framework\Model\ResourceModel\Db\Context $context,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        $connectionName = null
    ) {
        $this->_storeManager = $storeManager;
        parent::__construct($context, $connectionName);
    }

    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('folio3_conventionalformgridstorefilter', 'conventionalformgridstorefilter_id');
		$this->_conventionalformgridstorefilterTable = $this->getTable('folio3_conventionalformgridstorefilter');
        $this->_conventionalformgridstorefilterStoreTable = $this->getTable('folio3_conventionalformgridstorefilter_store');
    }

    /**
     * Perform actions before object save
     *
     * @param AbstractModel $object
     * @return $this
     */
    protected function _beforeSave(AbstractModel $object)
    {
        if ($object->hasData('stores') && is_array($object->getStores())) {
            $stores = $object->getStores();
            $stores[] = 0;
            $object->setStores($stores);
        } elseif ($object->hasData('stores')) {
            $object->setStores([$object->getStores(), 0]);
        }
        return $this;
    }

    /**
     * Perform actions after object save
     *
     * @param \Magento\Framework\Model\AbstractModel $object
     * @return $this
     */
    protected function _afterSave(AbstractModel $object)
    {
        $connection = $this->getConnection();

        /**
         * save stores
         */
        $stores = $object->getStores();
        if (!empty($stores)) {
            $condition = ['conventionalformgridstorefilter_id = ?' => $object->getId()];
            $connection->delete($this->_conventionalformgridstorefilterStoreTable, $condition);

            $insertedStoreIds = [];
            foreach ($stores as $storeId) {
                if (in_array($storeId, $insertedStoreIds)) {
                    continue;
                }

                $insertedStoreIds[] = $storeId;
                $storeInsert = ['store_id' => $storeId, 'conventionalformgridstorefilter_id' => $object->getId()];
                $connection->insert($this->_conventionalformgridstorefilterStoreTable, $storeInsert);
            }
        }

        return $this;
    }    

    /**
     * Perform actions after object load
     *
     * @param \Magento\Framework\Model\AbstractModel $object
     * @return $this
     */
    protected function _afterLoad(AbstractModel $object)
    {
        $connection = $this->getConnection();
        $select = $connection
            ->select()
            ->from($this->_conventionalformgridstorefilterStoreTable,['store_id'])
            ->where(
            'conventionalformgridstorefilter_id = :conventionalformgridstorefilter_id'
        );
        $stores = $connection->fetchCol($select, [':conventionalformgridstorefilter_id' => $object->getId()]);
        if (empty($stores) && $this->_storeManager->hasSingleStore()) {
            $object->setStores([$this->_storeManager->getStore(true)->getId()]);
        } else {
            $object->setStores($stores);
        }
        //return $this;
        return parent::_afterLoad($object);
    }    

    /**
     * Get load select
     *
     * @param string $field
     * @param mixed $value
     * @param \Magento\Framework\Model\AbstractModel $object
     * @return \Magento\Framework\DB\Select
     */
    protected function _getLoadSelect($field, $value, $object)
    {
        $select = parent::_getLoadSelect($field, $value, $object);
        if ($object->getStoreId()) {
            $select->join(
                ['cps' => $this->_conventionalformgridstorefilterStoreTable],
                $this->getMainTable() . '.conventionalformgridstorefilter_id = cps.conventionalformgridstorefilter_id'
            )->where(
                'cps.store_id IN (0, ?)',
                $object->getStoreId()
            )->order(
                'store_id DESC'
            )->limit(
                1
            );
        }
        
        return $select;
    }

}

 

Edit following CONTROLLER file, execute() method:

app/code/Folo3/ConventionalFormGridStoreFilter/Controller/Adminhtml/Index/Save.php

    public function execute()
    {
        $data = $this->getRequest()->getPostValue();
        if ($data) {
            $data = $this->dataProcessor->filter($data);
            $model = $this->_objectManager->create('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter');

            $id = $this->getRequest()->getParam('conventionalformgridstorefilter_id');
            if ($id) {
                $model->load($id);
            }
            
            // save image data and remove from data array
            if (isset($data['image'])) {
                $imageData = $data['image'];
                unset($data['image']);
            } else {
                $imageData = array();
            }

            /*
            store-field
            */
            if(!isset($data['stores'])) {
                $data['stores'] = array();
            }

            $model->addData($data);

            if (!$this->dataProcessor->validate($data)) {
                $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $model->getId(), '_current' => true]);
                return;
            }

            try {
                $imageHelper = $this->_objectManager->get('Folio3\ConventionalFormGridStoreFilter\Helper\Data');

                if (isset($imageData['delete']) && $model->getImage()) {
                    $imageHelper->removeImage($model->getImage());
                    $model->setImage(null);
                }
                
                $imageFile = $imageHelper->uploadImage('image');
                //print_r($imageFile);
                if ($imageFile) {
                    $model->setImage('ConventionalFormGridStoreFilter/'.$imageFile);
                }

                $model->save();
                $this->messageManager->addSuccess(__('The Data has been saved.'));
                $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false);
                if ($this->getRequest()->getParam('back')) {
                    $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $model->getId(), '_current' => true]);
                    return;
                }
                $this->_redirect('*/*/');
                return;
            } catch (\Magento\Framework\Model\Exception $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\RuntimeException $e) {
                $this->messageManager->addError($e->getMessage());
            } catch (\Exception $e) {
                $this->messageManager->addException($e, __('Something went wrong while saving the data.'));
            }

            $this->_getSession()->setFormData($data);
            $this->_redirect('*/*/edit', ['conventionalformgridstorefilter_id' => $this->getRequest()->getParam('conventionalformgridstorefilter_id')]);
            return;
        }
        $this->_redirect('*/*/');
    }

 

Note:

Rendering of store-field with CRUD operation is completed.

Step-5:

GRID work requires to edit following file(s).

Note:

The method “filterStoreCondition” will be used for filtering collection by store.

The addStoreData() will join store table with the main table collection.

app/code/Folo3/ConventionalFormGridStoreFilter/Block/Adminhtml/Lowstock/Grid.php

            $this->addColumn(
                'store_id',
                [
                    'header' => __('Store View'),
                    'index' => 'stores',
                    'type' => 'store',
                    'store_all' => true,
                    'store_view' => true,
                    'sortable' => false,
                    'filter_condition_callback' => [$this, '_filterStoreCondition'],
                    'renderer' => \Magento\Backend\Block\Widget\Grid\Column\Renderer\Store::class,
                ]
            );  




    /**
    /**
     * Prepare collection
     *
     * @return \Magento\Backend\Block\Widget\Grid
     */
    protected function _prepareCollection()
    {
        $collection = $this->_collectionFactory->create();
        /* @var $collection \Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter\Collection */
        $collection->addStoreData();
        $this->setCollection($collection);

        return parent::_prepareCollection();
    }

     * Filter store condition
     *
     * @param \Magento\Framework\Data\Collection $collection
     * @param \Magento\Framework\DataObject $column
     * @return void
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    protected function _filterStoreCondition($collection, \Magento\Framework\DataObject $column)
    {
        if (!($value = $column->getFilter()->getValue())) {
            return;
        }

        $this->getCollection()->addStoreFilter($value);
    }   

 

Step-6 (final step):

Insert the filtering logic by editing the following file:

app/code/Folo3/ConventionalFormGridStoreFilter/Model/ResourceModel/ConventionalFormGridStoreFilter/Collection.php

namespace Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{

    /**
     * main table
     *
     * @var string
     */
    protected $_conventionalformgridstorefilterTable = null;

    /**
     * store table
     *
     * @var string
     */
    protected $_conventionalformgridstorefilterStoreTable = null;    

    /**
     * Add store data flag
     * @var bool
     */
    protected $_addStoreDataFlag = false;

    /**
     * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
     * @param \Psr\Log\LoggerInterface $logger
     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param mixed $connection
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource
     */
    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        $this->_storeManager = $storeManager;
        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
    }

    /**
     * Resource initialization
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Folio3\ConventionalFormGridStoreFilter\Model\ConventionalFormGridStoreFilter', 'Folio3\ConventionalFormGridStoreFilter\Model\ResourceModel\ConventionalFormGridStoreFilter');
    }

    /**
     * Join fields to entity
     *
     * @return $this
     */
    protected function _joinFields()
    {
        $conventionalformgridstorefilterStoreTable = $this->getConventionalformgridstorefilterStoreTable();
        $this->getSelect()->join(
            ['rdt' => $conventionalformgridstorefilterStoreTable],
            'main_table.conventionalformgridstorefilter_id = rdt.conventionalformgridstorefilter_id',
            ['rdt.store_id']
        );

        return $this;
    }    

    /**
     * Add store filter
     *
     * @param int|int[] $storeId
     * @return $this
     */
    public function addStoreFilter($storeId)
    {
        $inCond = $this->getConnection()->prepareSqlCondition('store.store_id', ['in' => $storeId]);
        $this->getSelect()->join(
            ['store' => $this->getConventionalformgridstorefilterStoreTable()],
            'main_table.conventionalformgridstorefilter_id=store.conventionalformgridstorefilter_id',
            []
        );
        $this->getSelect()->where($inCond);
        return $this;
    }    

    /**
     * Add store data
     *
     * @return void
     */
    protected function _addStoreData()
    {        
        $connection = $this->getConnection();
        $conventionalformgridstorefilterIds = $this->getColumnValues('conventionalformgridstorefilter_id');
        $storesToConventionalformgridstorefilter = [];
        if (count($conventionalformgridstorefilterIds) > 0) {
            $conventionalformgridstorefilterIdCondition = $this->_getConditionSql('conventionalformgridstorefilter_id', ['in' => $conventionalformgridstorefilterIds]);
            $storeIdCondition = $this->_getConditionSql('store_id', ['gt' => 0]);
            $select = $connection->select()->from(
                $this->getConventionalformgridstorefilterStoreTable()
            )->where(
                $conventionalformgridstorefilterIdCondition
            )->where(
                $storeIdCondition
            );

            $result = $connection->fetchAll($select);
            foreach ($result as $row) {
                if (!isset($storesToConventionalformgridstorefilter[$row['conventionalformgridstorefilter_id']])) {
                    $storesToConventionalformgridstorefilter[$row['conventionalformgridstorefilter_id']] = [];
                }
                $storesToConventionalformgridstorefilter[$row['conventionalformgridstorefilter_id']][] = $row['store_id'];
            }
        }

        foreach ($this as $item) {
            if (isset($storesToConventionalformgridstorefilter[$item->getConventionalformgridstorefilterId()])) {
                $item->setData('stores', $storesToConventionalformgridstorefilter[$item->getConventionalformgridstorefilterId()]);
            } else {
                $item->setData('stores', []);
            }
        }
    }    

    /**
     * Get conventionalformgridstorefilter table
     *
     * @return string
     */
    protected function getConventionalformgridstorefilterTable()
    {
        if ($this->_conventionalformgridstorefilterTable === null) {
            $this->_conventionalformgridstorefilterTable = $this->getTable('folio3_conventionalformgridstorefilter');
        }
        return $this->_conventionalformgridstorefilterTable;
    }

    /**
     * Get conventionalformgridstorefilter store table
     *
     * @return string
     */
    protected function getConventionalformgridstorefilterStoreTable()
    {
        if ($this->_conventionalformgridstorefilterStoreTable === null) {
            $this->_conventionalformgridstorefilterStoreTable = $this->getTable('folio3_conventionalformgridstorefilter_store');
        }
        return $this->_conventionalformgridstorefilterStoreTable;
    }    

    /**
     * Add stores data
     *
     * @return $this
     */
    public function addStoreData()
    {
        $this->_addStoreDataFlag = true;
        return $this;
    }    

    /**
     * Redeclare parent method for store filters applying
     *
     * @return $this
     */
    protected function _beforeLoad()
    {
        parent::_beforeLoad();
        return $this;
    }    

    /**
     * Action after load
     *
     * @return $this
     */
    protected function _afterLoad()
    {
        parent::_afterLoad();
        if ($this->_addStoreDataFlag) {
            $this->_addStoreData();
        }
        return $this;
    }        
}

 

Please feel free to comment or reach out if you have any questions. If you need any help with customizing your Magento 2 web store, please get in touch with us.

CALL

USA408 365 4638

VISIT

1301 Shoreway Road, Suite 160,

Belmont, CA 94002

Contact us

Whether you are a large enterprise looking to augment your teams with experts resources or an SME looking to scale your business or a startup looking to build something.
We are your digital growth partner.

Tel: +1 408 365 4638
Support: +1 (408) 512 1812