Hi Friends,
If I talk about today’s blog it’s quite big as per the coding manner. Here, I have explained about the “How to create admin form with New, Save, Save And Continue, Edit, Delete & Mass Delete Action in Magento 2”.
If you remember our first blog in which I have explained the “How to create admin grid using UI Component step by step documentation” so I just continue with that sample module to easily go with that.
Please follow the below steps to create proper actions to work with your custom module.
Step 1: First, create the “New” action
Create New controller file Newbrand.php in following path app/code/Yournamespace/Brand/Controller/Adminhtml
Make sure you have added newbrand as URL in yournamespace_brand_branddetails_listing.xml file.
<?php
namespace Yournamespace\Brand\Controller\Adminhtml\Branddetails;
class Newbrand extends \Magento\Backend\App\Action
{
protected $resultPageFactory;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
public function execute() {
protected $_publicActions = ['newbrand'];
$this->_view->getPage()->getConfig()->getTitle()->prepend( __('New Brand Detail'));
$resultPage = $this->resultPageFactory->create();
$this->_setActiveMenu('Yournamespace_Brand::branddetails');
return $resultPage;
}
}
Step 2: Now, time to create DataProvider file
Create DataProvider.php in following path app/code/Yournamespace/Brand/Model/Branddetails
<?php
namespace Yournamespace\Brand\Model\Branddetails;
use Magento\Ui\DataProvider\AbstractDataProvider;
use Magento\Ui\DataProvider\Modifier\ModifierInterface;
use Magento\Ui\DataProvider\Modifier\PoolInterface;
use Yournamespace\Brand\Model\ResourceModel\Branddetails\CollectionFactory;
class DataProvider extends AbstractDataProvider
{
/**
* @var array
*/
protected $_loadedData;
public function __construct(
$name,
$primaryFieldName,
$requestFieldName,
CollectionFactory $CollectionFactory,
array $meta = [],
array $data = []
) {
$this->collection = $CollectionFactory->create();
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
}
public function getData()
{
if (isset($this->_loadedData)) {
return $this->_loadedData;
}
$items = $this->collection->getItems();
foreach ($items as $brand) {
$this->_loadedData[$brand->getEntityId()] = $brand->getData();
}
return $this->_loadedData;
}
}
Step 3: Create Block folder in app/code/Yournamespace/Brand
A. Create Generic.php file in following path app/code/Yournamespace/Brand/Block/Adminhtml/Branddetails/Edit/Buttons
<?php
namespace Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons;
use Magento\Backend\Block\Widget\Context;
use Magento\Framework\Exception\NoSuchEntityException;
use Yournamespace\Brand\Model\Api\Data\BrandInterface;
class Generic
{
protected $context;
protected $customform;
public function __construct(Context $context)
{
$this->context = $context;
}
public function getEntityId()
{
try
{
return $this->context->getRequest()->getParam('entity_id');
}
catch (NoSuchEntityException $e)
{
return null;
}
}
public function getUrl($route = '', $params = [])
{
return $this->context->getUrlBuilder()->getUrl($route, $params);
}
}
B. Create Save.php file in following path app/code/Yournamespace/Brand/Block/Adminhtml/Branddetails/Edit/Buttons
<?php
namespace Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Save extends Generic implements ButtonProviderInterface
{
public function getButtonData()
{
return [
'label' => __('Save Brand'),
'class' => 'save primary',
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'save']],
'form-role' => 'save',
],
'sort_order' => 90,
];
}
}
Step 4: Now create handle XML file to show admin form fields
Create handle xml file brand_branddetails_newbrand.xml in following path app/code/Yournamespace/Brand/view/adminhtml/layout
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<update handle="form_key"/>
<referenceContainer name="content">
<uiComponent name="admin_branddetails_fields"/>
</referenceContainer>
</body>
</page>
Step 5: Need to create source file for admin form field
Create Enabledisable.php in following path app/code/Yournamespace/Brand/Model/Config/Source
<?php
namespace Yournamespace\Brand\Model\Config\Source;
use Magento\Framework\Option\ArrayInterface;
class Enabledisable implements ArrayInterface
{
public function toOptionArray()
{
$options = [
0 => [
'label' => 'Active',
'value' => 1
],
1 => [
'label' => 'Deactive',
'value' => 0
]
];
return $options;
}
}
Step 6: Now, time to create UI Component file
Create admin_branddetails_fields.xml UI Component file in following folder app/code/Yournamespace/Brand/view/adminhtml/ui_component/
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">admin_branddetails_fields.admin_branddetails_fields_data_source</item>
<item name="deps" xsi:type="string">admin_branddetails_fields.admin_branddetails_fields_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Brand Details</item>
<item name="config" xsi:type="array">
<item name="dataScope" xsi:type="string">data</item>
<item name="namespace" xsi:type="string">admin_branddetails_fields</item>
</item>
<item name="buttons" xsi:type="array">
<item name="back" xsi:type="array">
<item name="name" xsi:type="string">Back</item>
<item name="label" xsi:type="string" translate="true">Back</item>
<item name="class" xsi:type="string">back</item>
<item name="url" xsi:type="string">*/*/index</item>
</item>
<item name="save" xsi:type="string">Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons\Save</item>
<item name="save_and_continue" xsi:type="string">Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons\SaveAndContinueButton</item>
<item name="delete" xsi:type="string">Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons\Delete</item>
</item>
<item name="template" xsi:type="string">templates/form/collapsible</item>
</argument>
<dataSource name="admin_branddetails_fields_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Yournamespace\Brand\Model\Branddetails\DataProvider</argument>
<argument name="name" xsi:type="string">admin_branddetails_fields_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">entity_id</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="submit_url" xsi:type="url" path="Branddetails/Branddetails/saveform"/>
</item>
</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
</item>
</argument>
</dataSource>
<fieldset name="Branddetails_details">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="collapsible" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Brand Details</item>
<item name="sortOrder" xsi:type="number">20</item>
</item>
</argument>
<field name="title">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Brand Name</item>
<item name="formElement" xsi:type="string">input</item>
<item name="source" xsi:type="string">Branddetails</item>
<item name="dataScope" xsi:type="string">title</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</argument>
</field>
<field name="url_key">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">URL Key</item>
<item name="formElement" xsi:type="string">input</item>
<item name="source" xsi:type="string">Branddetails</item>
<item name="dataScope" xsi:type="string">url_key</item>
</item>
</argument>
</field>
<field name="description">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">textarea</item>
<item name="label" xsi:type="string" translate="true">Description</item>
<item name="formElement" xsi:type="string">textarea</item>
<item name="source" xsi:type="string">Branddetails</item>
<item name="dataScope" xsi:type="string">description</item>
</item>
</argument>
</field>
<field name="status">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Yournamespace\Brand\Model\Config\Source\Enabledisable</item>
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">integer</item>
<item name="label" xsi:type="string" translate="true">Status</item>
<item name="formElement" xsi:type="string">select</item>
<item name="source" xsi:type="string">Branddetails</item>
<item name="dataScope" xsi:type="string">status</item>
</item>
</argument>
</field>
<field name="brand_image">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">image</item>
<item name="label" xsi:type="string" translate="true">Brand Image</item>
<item name="formElement" xsi:type="string">image</item>
<item name="source" xsi:type="string">Branddetails</item>
<item name="dataScope" xsi:type="string">brand_image</item>
</item>
</argument>
</field>
</fieldset>
</form>
Step 7: Now, I will create main “Save” action to save brand data
Create Savebrand.php in following path app/code/Yournamespace/Brand/Controller/Adminhtml/Branddetails
<?php
namespace Yournamespace\Brand\Controller\Adminhtml\Branddetails;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Yournamespace\Brand\Model\Branddetails;
class Savebrand extends Action
{
protected $request;
protected $_moduleFactory;
protected $resultRedirectFactory;
protected $jsonHelper;
protected $date;
public function __construct(Context $context, Branddetails $moduleFactory, \Magento\Framework\Json\Helper\Data $jsonHelper, \Magento\Framework\Stdlib\DateTime\DateTime $date)
{
$this->jsonHelper = $jsonHelper;
$this->date = $date;
$this->_moduleFactory = $moduleFactory;
parent::__construct($context);
}
public function execute() {
protected $_publicActions = ['savebrand'];
$resultRedirect = $this->resultRedirectFactory->create();
$data = $this->getRequest()->getPostValue();
$urlKey = $this->_objectManager->create('Magento\Catalog\Model\Product\Url')->formatUrlKey($data['url_key']);
try {
$id = (int)$this->getRequest()->getParam('entity_id');
$date = $this->date->gmtDate();
$objectManager = $this->_objectManager->create('Yournamespace\Brand\Model\Branddetails');
if($id){
$postdata = array(
'title' => $data['title'],
'url_key' => $urlKey,
'description' => $data['description'],
'status' => $data['status'],
'brand_image' => $data['brand_image'][0]['name'],
'brand_image_url' => $data['brand_image'][0]['url'],
'updated_at' => $date
);
$objectManager->setData($postdata)->setId($id);
$objectManager->save();
//echo '<pre>';print_r($objectManager->getData());die;
} else {
$postdata = array(
'title' => $data['title'],
'url_key' => $urlKey,
'description' => $data['description'],
'status' => $data['status'],
'brand_image' => $data['brand_image'][0]['name'],
'brand_image_url' => $data['brand_image'][0]['url'],
'created_at' => $date,
'updated_at' => $date
);
$objectManager->setData($postdata);
$objectManager->save();
$this->messageManager->addSuccessMessage(__('The Brand has been saved.'));
}
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(nl2br($e->getMessage()));
return $resultRedirect->setPath('*/*/editbrand');
}
if ($this->getRequest()->getParam('back')) {
$this->messageManager->addSuccessMessage(__('The Brand has been saved.'));
return $resultRedirect->setPath('*/*/editbrand', ['entity_id' => $id, '_current' => true]);
}
return $resultRedirect->setPath('*/*/index');
}
}
Step 8: Now, create the “Edit” action
Create new controller Editbrand.php in following path app/code/Yournamespace/Brand/Controller/Adminhtml/Branddetails/
<?php
namespace Yournamespace\Brand\Controller\Adminhtml\Branddetails;
use Magento\Backend\App\Action\Context;
class Editbrand extends \Magento\Backend\App\Action
{
protected $_coreRegistry = null;
public function __construct(Context $context, \Magento\Framework\Registry $coreRegistry)
{
$this->_coreRegistry = $coreRegistry;
parent::__construct($context);
}
public function execute()
{
protected $_publicActions = ['editbrand'];
$FromModel = $this->_objectManager->create('Yournamespace\Brand\Model\Branddetails');
$FormId = $this->getRequest()->getParam('entity_id');
if($FormId)
$FromModel->load($FormId);
$this->_coreRegistry->register('yournamespace_branddetails', $FromModel);
$this->_view->loadLayout();
$this->_setActiveMenu('Yournamespace_branddetails::branddetails');
if($FromModel->getEntityId())
{
$breadcrumbTitle = __('Edit Form');
$breadcrumbLabel = __('Edit Form');
}
else
{
$breadcrumbTitle = __('New Form');
$breadcrumbLabel = __('New Form');
}
$this->_view->getPage()->getConfig()->getTitle()->prepend(__('Manage Brand Details'));
$this->_view->getPage()->getConfig()->getTitle()->prepend($FromModel->getEntityId() ? __('Edit Form') : __('New Form'));
$this->_addBreadcrumb($breadcrumbLabel, $breadcrumbTitle);
// restore data
$values = $this->_getSession()->getData('yournamespace_branddetails', true);
if ($values) {
$FromModel->addData($values);
}
$this->_view->renderLayout();
}
}
Step 9: To show edit form we must need to create handle of edit action
Create new file brand_branddetails_editbrand.xml in following path app/code/Yournamespace/Brand/view/adminhtml/layout/
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<update handle="form_key"/>
<referenceContainer name="content">
<uiComponent name="admin_branddetails_fields"/>
</referenceContainer>
</body>
</page>
Step 10: Now, create the “Delete” action
Create new controller Deletebrand.php in following path app/code/Yournamespace/Brand/Controller/Adminhtml/Branddetails/
<?php
namespace Yournamespace\Brand\Controller\Adminhtml\Branddetails;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Yournamespace\Brand\Model\Branddetails;
class Deletebrand extends Action {
public function execute() {
protected $_publicActions = ['deletebrand'];
$id = $this->getRequest()->getParam('entity_id');
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
if ($id) {
$title = "";
try {
$model = $this->_objectManager->create('Yournamespace\Brand\Model\Branddetails');
$model->load($id);
$model->delete();
$this->messageManager->addSuccess(__('The brand has been deleted.'));
return $resultRedirect->setPath('*/*/index');
} catch (\Exception $e) {
$this->messageManager->addError($e->getMessage());
return $resultRedirect->setPath('*/*/editbrand', ['entity_id' => $id]);
}
}
}
}
Step 11: Now, I will create “Mass Delete” action which trigger from the grid
Create new controller Massdelete.php in following path app/code/Yournamespace/Brand/Controller/Adminhtml/Branddetails/
<?php
namespace Yournamespace\Brand\Controller\Adminhtml\Branddetails;
use Magento\Framework\Controller\ResultFactory;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Yournamespace\Brand\Model\ResourceModel\Branddetails\CollectionFactory;
class Massdelete extends \Magento\Backend\App\Action {
protected $filter;
protected $collectionFactory;
public function __construct(Context $context, Filter $filter, CollectionFactory $collectionFactory) {
$this->filter = $filter;
$this->collectionFactory = $collectionFactory;
parent::__construct($context);
}
public function execute() {
$collection = $this->filter->getCollection($this->collectionFactory->create());
$collectionSize = $collection->getSize();
foreach ($collection as $template) {
$template->delete();
}
$this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', $collectionSize));
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
return $resultRedirect->setPath('*/*/');
}
}
Step 12: To handle “Delete” action, I will create “Delete Button”
Create Delete.php in following path app/code/Yournamespace/Brand/Block/Adminhtml/Branddetails/Edit/Buttons
<?php
namespace Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Delete extends GenericButton implements ButtonProviderInterface
{
public function getButtonData()
{
return [
'label' => __('Delete'),
'on_click' => 'deleteConfirm(\'' . __('Are you sure you want to delete this log?') . '\', \'' . $this->getDeleteUrl() . '\')',
'class' => 'delete',
'sort_order' => 20
];
}
public function getDeleteUrl()
{
$id = $this->getId();
return $this->getUrl('*/*/deletebrand', ['id' => 76]);
}
}
Step 13: Last, create “Save and continue Button”
Create SaveAndContinueButton.php in following path app/code/Yournamespace/Brand/Block/Adminhtml/Branddetails/Edit/Buttons
<?php
namespace Yournamespace\Brand\Block\Adminhtml\Branddetails\Edit\Buttons;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class SaveAndContinueButton extends Generic implements ButtonProviderInterface
{
public function getButtonData()
{
return [
'label' => __('Save and Continue Edit'),
'class' => 'save',
'data_attribute' => [
'mage-init' => [
'button' => ['event' => 'saveAndContinueEdit'],
],
],
'sort_order' => 80,
];
}
}
Step 14: Now, RUN the below command.
1. php bin/magento setup:di:compile
2. php bin/magento setup:static-content:deploy
3. php bin/magento cache:flush
These are all the above steps to create different Actions in your custom module.
For the basic custom module, CRUD operation is enough but if you want to go one step ahead then I will suggest choosing the “Mass Delete” action.
I personally suggest you guys use the “Save and Continue Button” action because it will keep you on the same page after saving the data.
Thank you for reading this post.