Create Admin Grid and Form Magento 2

How to Create Admin Grid and Form without UI Component in Magento 2?

Today, we are going to teach you how to create an admin grid and form without UI component in Magento 2.

The admin grid is basically a kind of table that lists items in your database tables with features like filter, update, sort, delete, etc.

Form, on the other hand, is also essential for Magento 2 eCommerce stores. And like the admin grid, we will also show you how to create admin form without UI component in this tutorial.

Now, you can most certainly create both the admin grid and form using UI components, but they’re a bit complex in structure, which is why the majority of people prefer using the block methods.

So, let’s learn how to create admin grid and form without UI components in Magento 2.

Steps to Create Admin Grid & Form without UI Component in Magento 2

To create admin grid and form without UI component, please follow the below steps.

Step #1

First of all, we will create a registration.php file for registering our module in pp/code/Md/Blog/ and add the following code into the file.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Md_Blog', __DIR__);

Step #2

Now, we will create a module.xml file to define our module in app/code/Md/Blog/etc/ and add the following code.

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

Step #3

Next, we will need to create an InstallSchema.php file to create our database in app/code/Md/Blog/Setup/ and copy the following code into the file.

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Md\Blog\Setup;
use Magento\Framework\DB\Ddl\Table;
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();
/**
* Create table 'Md_blog'
*/
if (!$installer->tableExists('Md_blog')) {
$table = $installer->getConnection()->newTable(
$installer->getTable('Md_blog')
)->addColumn(
'id',
Table::TYPE_INTEGER,
null,
[
'identity' => true,
'nullable' => false,
'primary' => true,
'unsigned' => true,
],
'ID'
)->addColumn(
'name',
Table::TYPE_TEXT,
255,
['nullable => false'],
'Name'
)->addColumn(
'title',
Table::TYPE_TEXT,
'255',
['nullable => false'],
'Blog Title'
)->addColumn(
'content',
Table::TYPE_TEXT,
'2M',
[],
'Blog Content'
)->addColumn(
'status',
Table::TYPE_SMALLINT,
null,
['nullable' => false],
'Status'
)->addColumn(
'created_at',
Table::TYPE_TIMESTAMP,
null,
['nullable' => false, 'default' => Table::TIMESTAMP_INIT],
'Created At'
)->setComment('Blog Table');
$installer->getConnection()->createTable($table);
}
$installer->endSetup();
}
}

Step #4

After that, we will need to take care of the business logic and a single instance of object. So, let’s create a blog.php model file in app/code/Md/Blog/Model/ and copy the following code into the file.

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Md\Blog\Model;
class Blog extends \Magento\Framework\Model\AbstractModel {
protected function _construct() {
$this->_init('Md\Blog\Model\ResourceModel\Blog');
}
}

Step #5

The next step is to now create a blog.php resource model in app/code/Md/Blog/Model/ResourceModel/ for data mapping of the storage structure.

Once you create the resource model file, copy the following code.

<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Md\Blog\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Blog extends AbstractDb {
/**
* Initialize resource model
*
* @return void
*/
protected function _construct() {
$this->_init('Md_blog', 'id');
}
}

Step #6

Now, we will need to set a model as well as a resource model file and manage the collection.

So, create a collection.php file in app/code/Md/Blog/Model/ResourceModel/Blog/ and copy the following code into the file.

<?php

/**

* Copyright © 2015 Magento. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Model\ResourceModel\Blog;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection {

protected function _construct() {

$this->_init('Md\Blog\Model\Blog', 'Md\Blog\Model\ResourceModel\Blog');

}

}

Step #7

Next, we will have to create a status.php optionArray file in app/code/Md/Blog/Model/

to display status enable disable option.

<?php

/**

* Copyright © 2015 Magento. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Model;

class Status implements \Magento\Framework\Option\ArrayInterface {

const STATUS_ENABLED = 1;

const STATUS_DISABLED = 2;

public function toOptionArray() {

return [

[

self::STATUS_ENABLED => __('Enabled'),

self::STATUS_DISABLED => __('Disabled'),

],

];

}

public static function getOptionArray()

{

return [self::STATUS_ENABLED => __('Enabled'), self::STATUS_DISABLED => __('Disabled')];

}

}

Step #8

Now, the next step is to add an admin router of the module.

For that, we need to create a routes.xml file in app/code/Md/Blog/etc/adminhtml/ and copy the following code into the file.

<?xml version="1.0"?>

<!--

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

-->

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">

<router id="admin">

<route id="blog" frontName="blog">

<module name="Md_Blog" before="Magento_Adminhtml" />

</route>

</router>

</config>

Step #9

Next, we will have to add link in admin menu for which we need to create a menu.xml file in app/code/Md/Blog/etc/adminhtml/ directory and copy the following code.

<?xml version="1.0"?>

<!--

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

-->

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Backend/etc/menu.xsd">

<menu>

<add id="Md_Blog::view" title="Md Blog" module="MdBlog" sortOrder="10" resource="Md_Blog::view"/>

<add id="Md_Blog::grid" title="Manage Blog Records" module="Md_Blog" sortOrder="9" parent="Md_Blog::view" action="blog/grid/index" resource="Md_Blog::view"/>

</menu>

</config>

Step #10

Now, we need to create a Grid.php file for the backend grind container block in app/code/Md/Blog/Block/Adminhtml/ directory and copy the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml;

/**

* Backend grid container block

*/

class Grid extends \Magento\Backend\Block\Widget\Container {

/**

* @var string

*/

protected $_template = 'grid/view.phtml';

/**

* @param \Magento\Backend\Block\Widget\Context $context

* @param array                                 $data

*/

public function __construct(

\Magento\Backend\Block\Widget\Context $context,

array $data = []

) {

parent::__construct($context, $data);

}

/**

* {@inheritdoc}

*/

protected function _prepareLayout() {

$addButtonProps = [

'id' => 'add_new_grid',

'label' => __('Add New'),

'class' => 'add',

'button_class' => '',

'class_name' => 'Magento\Backend\Block\Widget\Button\SplitButton',

'options' => $this->_getAddButtonOptions(),

];

$this->buttonList->add('add_new', $addButtonProps);

$this->setChild('grid', $this->getLayout()->createBlock('Md\Blog\Block\Adminhtml\Grid\Grid', 'grid.view.grid'));

return parent::_prepareLayout();

}

/**

* @return array

*/

protected function _getAddButtonOptions() {

$splitButtonOptions[] = [

'label' => __('Add New'),

'onclick' => "setLocation('" . $this->_getCreateUrl() . "')",

];

return $splitButtonOptions;

}

/**

* @return string

*/

protected function _getCreateUrl() {

return $this->getUrl('blog/*/new');

}

/**

* @return string

*/

public function getGridHtml() {

return $this->getChildHtml('grid');

}

}

Step #11

After that, we will also create a Grid.php file in app/code/Md/Blog/Block/Adminhtml/Grid/ for adding a column in the grid.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml\Grid;

/**

* Adminhtml block grid demo records grid block

*

*/

class Grid extends \Magento\Backend\Block\Widget\Grid\Extended {

/**

* @var \Magento\Framework\Module\Manager

*/

protected $moduleManager;

/**

* @var \Md\Blog\Model\BlogFactory

*/

protected $_blogFactory;

/**

* @var \Md\Blog\Model\Status

*/

protected $_status;

/**

* @param \Magento\Backend\Block\Template\Context $context

* @param \Magento\Backend\Helper\Data            $backendHelper

* @param \Md\Blog\Model\BlogFactory              $blogFactory

* @param \Md\Blog\Model\Status                   $status

* @param \Magento\Framework\Module\Manager       $moduleManager

* @param array                                   $data

*/

public function __construct(

\Magento\Backend\Block\Template\Context $context,

\Magento\Backend\Helper\Data $backendHelper,

\Md\Blog\Model\BlogFactory $blogFactory,

\Md\Blog\Model\Status $status,

\Magento\Framework\Module\Manager $moduleManager,

array $data = []

) {

$this->_blogFactory = $blogFactory;

$this->_status = $status;

$this->moduleManager = $moduleManager;

parent::__construct($context, $backendHelper, $data);

}

/**

* @return void

*/

protected function _construct() {

parent::_construct();

$this->setId('gridGrid');

$this->setDefaultSort('id');

$this->setDefaultDir('DESC');

$this->setSaveParametersInSession(true);

$this->setUseAjax(true);

$this->setVarNameFilter('grid_record');

}

/**

* @return $this

*/

protected function _prepareCollection() {

$collection = $this->_blogFactory->create()->getCollection();

$this->setCollection($collection);

parent::_prepareCollection();

return $this;

}

/**

* @return $this

*/

protected function _prepareColumns() {

$this->addColumn(

'id',

[

'header' => __('ID'),

'type' => 'number',

'index' => 'id',

'header_css_class' => 'col-id',

'column_css_class' => 'col-id',

]

);

$this->addColumn(

'name',

[

'header' => __('Name'),

'index' => 'name',

]

);

$this->addColumn(

'title',

[

'header' => __('Title'),

'index' => 'title',

]

);

$this->addColumn(

'status',

[

'header' => __('Status'),

'index' => 'status',

'type' => 'options',

'options' => $this->_status->getOptionArray(),

]

);

$this->addColumn(

'created_at',

[

'header' => __('Created At'),

'index' => 'created_at',

]

);

$this->addColumn(

'edit',

[

'header' => __('Edit'),

'type' => 'action',

'getter' => 'getId',

'actions' => [

[

'caption' => __('Edit'),

'url' => [

'base' => 'blog/*/edit',

],

'field' => 'id',

],

],

'filter' => false,

'sortable' => false,

'index' => 'stores',

'header_css_class' => 'col-action',

'column_css_class' => 'col-action',

]

);

$this->addColumn(

'delete',

[

'header' => __('Delete'),

'type' => 'action',

'getter' => 'getId',

'actions' => [

[

'caption' => __('Delete'),

'url' => [

'base' => 'blog/*/delete',

],

'field' => 'id',

],

],

'filter' => false,

'sortable' => false,

'index' => 'stores',

'header_css_class' => 'col-action',

'column_css_class' => 'col-action',

]

);

$block = $this->getLayout()->getBlock('grid.bottom.links');

if ($block) {

$this->setChild('grid.bottom.links', $block);

}

return parent::_prepareColumns();

}

/**

* @return $this

*/

protected function _prepareMassaction() {

$this->setMassactionIdField('id');

$this->getMassactionBlock()->setFormFieldName('id');

$this->getMassactionBlock()->addItem(

'delete',

[

'label' => __('Delete'),

'url' => $this->getUrl('blog/*/massDelete'),

'confirm' => __('Are you sure?'),

]

);

$statuses = $this->_status->toOptionArray();

array_unshift($statuses, ['label' => '', 'value' => '']);

$this->getMassactionBlock()->addItem(

'status',

[

'label' => __('Change status'),

'url' => $this->getUrl('blog/*/massStatus', ['_current' => true]),

'additional' => [

'visibility' => [

'name' => 'status',

'type' => 'select',

'class' => 'required-entry',

'label' => __('Status'),

'values' => $statuses,

],

],

]

);

return $this;

}

/**

* @return string

*/

public function getGridUrl() {

return $this->getUrl('blog/*/grid', ['_current' => true]);

}

/**

* @return string

*/

public function getRowUrl($row) {

return $this->getUrl('blog/*/edit', ['id' => $row->getId()]);

}

}

Step #12

The next step now is to create a block edit page layout and add buttons.

So, create an Edit.php file in app/code/Md/Blog/Block/Adminhtml/Grid/ directory and copy the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml\Grid;

/**

* Block for edit 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);

}

/**

* Init container

*

* @return void

*/

protected function _construct() {

$this->_objectId = 'id';

$this->_blockGroup = 'Md_blog';

$this->_controller = 'adminhtml_grid';

parent::_construct();

$this->buttonList->update('save', 'label', __('Save Grid'));

$this->buttonList->add(

'saveandcontinue',

[

'label' => __('Save and Continue Edit'),

'class' => 'save',

'data_attribute' => [

'mage-init' => [

'button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form'],

],

],

],

-100

);

$this->buttonList->update('delete', 'label', __('Delete'));

}

/**

* Get edit form container header text

*

* @return \Magento\Framework\Phrase|string

*/

public function getHeaderText() {

if ($this->_coreRegistry->registry('Md_blog_form_data')->getId()) {

return __("Edit Post '%1'", $this->escapeHtml($this->_coreRegistry->registry('Md_blog_form_data')->getTitle()));

} else {

return __('New Record');

}

}

/**

* Retrieve the save and continue edit Url.

*

* @return string

*/

protected function _getSaveAndContinueUrl() {

return $this->getUrl('blog/*/save', ['_current' => true, 'back' => 'edit', 'active_tab' => '{{tab_id}}']);

}

/**

* Prepare the layout.

*

* @return $this

*/

protected function _prepareLayout() {

$this->_formScripts[] = "

function toggleEditor() {

if (tinyMCE.getInstanceById('page_content') == null) {

tinyMCE.execCommand('mceAddControl', false, 'content');

} else {

tinyMCE.execCommand('mceRemoveControl', false, 'content');

}

};

";

return parent::_prepareLayout();

}

}

Step #13

Now, we will also need to create a form object and set appropriate values in the form.

So, let’s create a Form.php file in app/code/Md/Blog/Block/Adminhtml/Grid/Edit/ directory and copy the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml\Grid\Edit;

/**

* Adminhtml block grid edit form block

*/

class Form extends \Magento\Backend\Block\Widget\Form\Generic {

/**

* Prepare the 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();

}

}

Step #14

After that, we need to create a Tabs.php file in app/code/Md/Blog/Block/Admimhtml/Grid/Edit/ to create form tab left menu and add the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml\Grid\Edit;

/**

* Admin blog left menu

*

*/

class Tabs extends \Magento\Backend\Block\Widget\Tabs {

/**

* @return void

*/

protected function _construct() {

parent::_construct();

$this->setId('grid_record');

$this->setDestElementId('edit_form');

$this->setTitle(__('Blog Information'));

}

}

Step #15

Next, we need to create tabs form elements. And for that, we need to create a Main.php file in app/code/Md/Blog/Block/Adminhtml/Grid/Edit/Tab/ and copy the following code into the file.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Block\Adminhtml\Grid\Edit\Tab;

use Magento\Backend\Block\Widget\Form\Generic;

use Magento\Backend\Block\Widget\Tab\TabInterface;

/**

* Blog form block

*/

class Main extends Generic implements TabInterface {

/**

* Core registry

*

* @var \Magento\Framework\Registry

*/

protected $_coreRegistry = null;

/**

* @var \Magento\Backend\Model\Auth\Session

*/

protected $_adminSession;

/**

* @var \Md\Blog\Model\Status

*/

protected $_status;

/**

* @param \Magento\Backend\Block\Template\Context $context

* @param \Magento\Framework\Registry             $registry

* @param \Magento\Framework\Data\FormFactory     $formFactory

* @param \Magento\Backend\Model\Auth\Session     $adminSession

* @param \Md\Blog\Model\Status                   $status

* @param array                                   $data

*/

public function __construct(

\Magento\Backend\Block\Template\Context $context,

\Magento\Framework\Registry $registry,

\Magento\Framework\Data\FormFactory $formFactory,

\Magento\Backend\Model\Auth\Session $adminSession,

\Md\Blog\Model\Status $status,

array $data = []

) {

$this->_status = $status;

$this->_adminSession = $adminSession;

parent::__construct($context, $registry, $formFactory, $data);

}

/**

* Prepare the form.

*

* @return $this

*/

protected function _prepareForm() {

$model = $this->_coreRegistry->registry('Md_blog_form_data');

$isElementDisabled = false;

$form = $this->_formFactory->create();

$form->setHtmlIdPrefix('page_');

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

if ($model->getId()) {

$fieldset->addField('id', 'hidden', ['name' => 'id']);

}

$fieldset->addField(

'name',

'text',

[

'name' => 'name',

'label' => __('Name'),

'title' => __('Name'),

'required' => true,

'value' => $this->_adminSession->getUser()->getFirstname(),

'disabled' => $isElementDisabled,

]

);

$fieldset->addField(

'title',

'text',

[

'name' => 'title',

'label' => __('Blog Title'),

'title' => __('Blog Title'),

'required' => true,

'disabled' => $isElementDisabled,

]

);

$contentField = $fieldset->addField(

'content',

'textarea',

[

'name' => 'content',

'label' => __('Content'),

'title' => __('Content'),

'required' => true,

'disabled' => $isElementDisabled,

]

);

$dateFormat = $this->_localeDate->getDateFormat(\IntlDateFormatter::SHORT);

$fieldset->addField(

'status',

'select',

[

'label' => __('Status'),

'title' => __('Status'),

'name' => 'status',

'required' => true,

'options' => $this->_status->getOptionArray(),

'disabled' => $isElementDisabled,

]

);

if (!$model->getId()) {

$model->setData('status', $isElementDisabled ? '0' : '1');

}

$form->addValues($model->getData());

$this->setForm($form);

return parent::_prepareForm();

}

/**

* Return Tab label

*

* @return \Magento\Framework\Phrase

*/

public function getTabLabel() {

return __('Blog Information');

}

/**

* Return Tab title

*

* @return \Magento\Framework\Phrase

*/

public function getTabTitle() {

return __('Blog Information');

}

/**

* Can show tab in tabs

*

* @return boolean

*/

public function canShowTab() {

return true;

}

/**

* Tab is hidden

*

* @return boolean

*/

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 #16

The next step is to create an Index.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/ directory for the action file for the grid page.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;

use Magento\Backend\App\Action\Context;

use Magento\Framework\View\Result\PageFactory;

/**

* Main page controller

*/

class Index extends Action {

/**

* @var PageFactory

*/

protected $resultPageFactory;

/**

* @param Context     $context

* @param PageFactory $resultPageFactory

*/

public function __construct(

Context $context,

PageFactory $resultPageFactory

) {

parent::__construct($context);

$this->resultPageFactory = $resultPageFactory;

}

/**

* @return \Magento\Framework\View\Result\PageFactory

*/

public function execute() {

$resultPage = $this->resultPageFactory->create();

$resultPage->setActiveMenu('MD_Blog::grid');

$resultPage->addBreadcrumb(__('Manage Grid View'), __('Manage Grid View'));

$resultPage->getConfig()->getTitle()->prepend(__('Manage Blog'));

return $resultPage;

}

}

Step #17

Now, we will have to set HTML content of grid columns. For that, we need to create a Grid.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/ directory and add the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;

use Magento\Backend\App\Action\Context;

use Magento\Framework\Controller\Result\RawFactory;

use Magento\Framework\View\LayoutFactory;

/**

* Grid Controller

*/

class Grid extends Action {

/**

* @var Rawfactory

*/

protected $resultRawFactory;

/**

* @var LayoutFactory

*/

protected $layoutFactory;

/**

* @param Context       $context

* @param Rawfactory    $resultRawFactory

* @param LayoutFactory $layoutFactory

*/

public function __construct(

Context $context,

Rawfactory $resultRawFactory,

LayoutFactory $layoutFactory

) {

parent::__construct($context);

$this->resultRawFactory = $resultRawFactory;

$this->layoutFactory = $layoutFactory;

}

/**

* @return \Magento\Framework\Controller\Result\RawFactory

*/

public function execute() {

$resultRaw = $this->resultRawFactory->create();

$blogHtml = $this->layoutFactory->create()->createBlock(

'Md\Blog\Block\Adminhtml\Grid\Grid',

'grid.view.grid'

)->toHtml();

return $resultRaw->setContents($blogHtml);

}

}

Step #18

Now, create a NewAction.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/ directory for new record action and add the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

/**

* New Record Form Controller

*/

class NewAction extends \Magento\Backend\App\Action {

/**

* @var \Magento\Backend\Model\View\Result\ForwardFactory

*/

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);

}

/**

* Create new blog record page

*

* @return \Magento\Backend\Model\View\Result\ForwardFactory

*/

public function execute() {

$resultForward = $this->resultForwardFactory->create();

return $resultForward->forward('edit');

}

/**

* @return boolean

*/

protected function _isAllowed() {

return true;

}

}

Step #19

The next step is to create an Edit.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/

to edit form action.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;

use Magento\Framework\Controller\ResultFactory;

/**

* Edit form controller

*/

class Edit extends \Magento\Backend\App\Action {

/**

* Core registry

*

* @var \Magento\Framework\Registry

*/

protected $_coreRegistry = null;

/**

* @var \Magento\Backend\Model\Session

*/

protected $adminSession;

/**

* @var \Md\Blog\Model\BlogFactory

*/

protected $blogFactory;

/**

* @param Action\Context                 $context

* @param \Magento\Framework\Registry    $registry

* @param \Magento\Backend\Model\Session $adminSession

* @param \Md\Blog\Model\BlogFactory     $blogFactory

*/

public function __construct(

Action\Context $context,

\Magento\Framework\Registry $registry,

\Magento\Backend\Model\Session $adminSession,

\Md\Blog\Model\BlogFactory $blogFactory

) {

$this->_coreRegistry = $registry;

$this->adminSession = $adminSession;

$this->blogFactory = $blogFactory;

parent::__construct($context);

}

/**

* @return boolean

*/

protected function _isAllowed() {

return true;

}

/**

* Add blog breadcrumbs

*

* @return $this

*/

protected function _initAction() {

/** @var \Magento\Backend\Model\View\Result\Page $resultPage */

$resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);

$resultPage->setActiveMenu('MD_Blog::grid')

->addBreadcrumb(__('Blog'), __('Blog'))

->addBreadcrumb(__('Manage Blog'), __('Manage Blog'));

return $resultPage;

}

/**

* @return \Magento\Backend\Model\View\Result\Page

*/

public function execute() {

$id = $this->getRequest()->getParam('id');

$model = $this->blogFactory->create();

if ($id) {

$model->load($id);

if (!$model->getId()) {

$this->messageManager->addError(__('This blog record no longer exists.'));

$resultRedirect = $this->resultRedirectFactory->create();

return $resultRedirect->setPath('*/*/');

}

}

$data = $this->adminSession->getFormData(true);

if (!empty($data)) {

$model->setData($data);

}

$this->_coreRegistry->register('Md_blog_form_data', $model);

$resultPage = $this->_initAction();

$resultPage->addBreadcrumb(

$id ? __('Edit Post') : __('New Blog'),

$id ? __('Edit Post') : __('New Blog')

);

$resultPage->getConfig()->getTitle()->prepend(__('Grids'));

$resultPage->getConfig()->getTitle()

->prepend($model->getId() ? $model->getTitle() : __('New Blog'));

return $resultPage;

}

}

Step #20

After that, we will also have to create a Delete.php file in app/code/Md/Controller/Adminhtml/Grid/ to delete record action.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;

use Magento\Backend\App\Action\Context;

/**

* Delete Controller

*/

class Delete extends \Magento\Backend\App\Action {

/**

* @var \Md\Blog\Model\BlogFactory

*/

protected $blogFactory;

/**

* @param Context                    $context

* @param \Md\Blog\Model\BlogFactory $blogFactory

*/

public function __construct(

Context $context,

\Md\Blog\Model\BlogFactory $blogFactory

) {

parent::__construct($context);

$this->blogFactory = $blogFactory;

}

/**

* @return bool

*/

protected function _isAllowed() {

return $this->_authorization->isAllowed('MD_Blog::view');

}

/**

* @return \Magento\Backend\Model\View\Result\Redirect

*/

public function execute() {

$id = $this->getRequest()->getParam('id');

$resultRedirect = $this->resultRedirectFactory->create();

if ($id) {

try {

$model = $this->blogFactory->create();

$model->load($id);

$model->delete();

$this->messageManager->addSuccess(__('The post has been deleted.'));

return $resultRedirect->setPath('*/*/');

} catch (\Exception $e) {

$this->messageManager->addError($e->getMessage());

return $resultRedirect->setPath('*/*/index', ['id' => $id]);

}

}

$this->messageManager->addError(__('We can\'t find a post to delete.'));

return $resultRedirect->setPath('*/*/');

}

}

Step #21

Next, we will create a Save.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/ directory to save the records in the database.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action;

use Magento\Backend\Model\Auth\Session;

class Save extends \Magento\Backend\App\Action {

/**

* @var \Magento\Backend\Model\Auth\Session

*/

protected $_adminSession;

/**

* @var \Md\Blog\Model\BlogFactory

*/

protected $blogFactory;

/**

* @param Action\Context                      $context

* @param \Magento\Backend\Model\Auth\Session $adminSession

* @param \Md\Blog\Model\BlogFactory          $blogFactory

*/

public function __construct(

Action\Context $context,

\Magento\Backend\Model\Auth\Session $adminSession,

\Md\Blog\Model\BlogFactory $blogFactory

) {

parent::__construct($context);

$this->_adminSession = $adminSession;

$this->blogFactory = $blogFactory;

}

/**

* Save blog record action

*

* @return \Magento\Backend\Model\View\Result\Redirect

*/

public function execute() {

$postObj = $this->getRequest()->getPostValue();

$name = $postObj["name"];

$date = date("Y-m-d");

$username = $this->_adminSession->getUser()->getFirstname();

if ($username == $name) {

$username = $this->_adminSession->getUser()->getFirstname();

} else {

$username = $name;

}

$userDetail = ["name" => $username, "created_at" => $date];

$data = array_merge($postObj, $userDetail);

$resultRedirect = $this->resultRedirectFactory->create();

if ($data) {

$model = $this->blogFactory->create();

$id = $this->getRequest()->getParam('id');

if ($id) {

$model->load($id);

}

$model->setData($data);

try {

$model->save();

$this->messageManager->addSuccess(__('The data has been saved.'));

$this->_adminSession->setFormData(false);

if ($this->getRequest()->getParam('back')) {

return $resultRedirect->setPath('blog/*/edit', ['id' => $model->getId(), '_current' => true]);

}

return $resultRedirect->setPath('*/*/');

} catch (\Magento\Framework\Exception\LocalizedException $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);

return $resultRedirect->setPath('*/*/edit', ['id' => $this->getRequest()->getParam('id')]);

}

return $resultRedirect->setPath('*/*/');

}

}

Step #22

Now, we will need to create a MassDelete.php file for adding mass delete records action.

So, create the file in app/code/Md/Blog/Controller/Adminhtml/Grid/

directory and add the following code.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action\Context;

use Magento\Framework\Controller\ResultFactory;

use Magento\Ui\Component\MassAction\Filter;

use Md\Blog\Model\ResourceModel\Blog\CollectionFactory;

/**

* Mass Delete Record Controller

*/

class MassDelete extends \Magento\Backend\App\Action {

/**

* @var Filter

*/

protected $filter;

/**

* @var CollectionFactory

*/

protected $collectionFactory;

/**

* @param Context           $context

* @param Filter            $filter

* @param CollectionFactory $collectionFactory

*/

public function __construct(

Context $context,

Filter $filter,

CollectionFactory $collectionFactory

) {

$this->filter = $filter;

$this->collectionFactory = $collectionFactory;

parent::__construct($context);

}

/**

* @return \Magento\Backend\Model\View\Result\Redirect

*/

public function execute() {

$deleteIds = $this->getRequest()->getPost('id');

$collection = $this->collectionFactory->create();

$collection->addFieldToFilter('id', ['in' => $deleteIds]);

$delete = 0;

foreach ($collection as $item) {

$item->delete();

$delete++;

}

$this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', $delete));

$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);

return $resultRedirect->setPath('*/*/');

}

}

Step #23

Next, we will need to create a MassStatus.php file in app/code/Md/Blog/Controller/Adminhtml/Grid/ directory for mass status update action.

<?php

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

namespace Md\Blog\Controller\Adminhtml\Grid;

use Magento\Backend\App\Action\Context;

use Magento\Framework\Controller\ResultFactory;

use Magento\Ui\Component\MassAction\Filter;

use Md\Blog\Model\ResourceModel\Blog\CollectionFactory;

/**

* Mass status update controller

*/

class MassStatus extends \Magento\Backend\App\Action {

/**

* @var Filter

*/

protected $filter;

/**

* @var CollectionFactory

*/

protected $collectionFactory;

/**

* @param Context           $context

* @param Filter            $filter

* @param CollectionFactory $collectionFactory

*/

public function __construct(

Context $context,

Filter $filter,

CollectionFactory $collectionFactory

) {

$this->filter = $filter;

$this->collectionFactory = $collectionFactory;

parent::__construct($context);

}

/**

* Update product(s) status action

*

* @return \Magento\Backend\Model\View\Result\Redirect

*/

public function execute() {

$ids = $this->getRequest()->getPost('id');

$status = $this->getRequest()->getPost('status');

$collection = $this->collectionFactory->create();

$collection->addFieldToFilter('id', ['in' => $ids]);

$updateStatus = 0;

try {

foreach ($collection as $item) {

$item->setStatus($status)->save();

$updateStatus++;

}

} catch (Exception $e) {

$this->messageManager->addExceptionMessage(

$e,

__('Something went wrong while updating the product(s) status.')

);

}

$this->messageManager->addSuccess(__('A total of %1 record(s) have been updated.', $updateStatus));

/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */

$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);

return $resultRedirect->setPath('*/*/');

}

}

Step #24

Now, we need to create layout of index page. And for that, we will have to create a blog_grid_index.xml file in app/code/Md/Blog/view/adminhtml/layout/ directory and add the following code.

<?xml version="1.0"?>

<!--

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

-->

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">

<body>

<referenceContainer name="content">

<block class="Md\Blog\Block\Adminhtml\Grid" name="grid_grid_listing"/>

</referenceContainer>

</body>

</page>

Step #25

Now, create a blog_grid_edit.xml file in app/code/Md/Blog/view/adminhtml/layout/ directory to create layout of edit page and add the following code.

<?xml version="1.0"?>

<!--

/**

* Copyright © Magento, Inc. All rights reserved.

* See COPYING.txt for license details.

*/

-->

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">

<update handle="editor"/>

<body>

<referenceContainer name="content">

<block class="Md\Blog\Block\Adminhtml\Grid\Edit" name="grid_grid_edit"/>

</referenceContainer>

<referenceContainer name="left">

<block class="Md\Blog\Block\Adminhtml\Grid\Edit\Tabs" name="grid_grid_edit_tabs">

<block class="Md\Blog\Block\Adminhtml\Grid\Edit\Tab\Main" name="grid_grid_edit_tab_main"/>

<action method="addTab">

<argument name="name" xsi:type="string">main_section</argument>

<argument name="block" xsi:type="string">grid_grid_edit_tab_main</argument>

</action>

</block>

</referenceContainer>

</body>

</page>

Step #26

Lastly, we need to display grid column HTML content. And for that, we need to create a View.phtml file in app/code/Md/Blog/view/adminhtml/templates/grid/ and add the following code.

<?php echo $block->getGridHtml(); ?>

And it’s done!

Now, we need to just setup the upgrade module and clean cache by executing the following commands.

php bin/magento s:up

php bin/magento s:s:d -f

php bin/magento c:c

Output:

As you execute the above commands, you’ll see an output like below for Magento 2 Grid without UI Component.

And Magento 2 Form without UI Component:

Create Admin Grid UI

Final Words…

With this, we have come to the end of our tutorial on how to create admin grid and form without UI component in Magento 2.

We hope that you found this tutorial helpful. If you have any questions or doubts, let us know in the comments below.

And if you need our professional assistance, feel free to Magento development company.

Tags