How to Create Admin Form With New, Save, And Continue, Edit, Delete & Mass Delete Actions?

7

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.

About the author

I’m Magento Certified Developer having quite 5 years of commercial development expertise in Magento as well as in Shopify. I’ve worked primarily with the Magento and Shopify e-commerce platform, managing the complexities concerned in building e-commerce solutions tailored to a client’s specific desires.

Related Posts

Leave a Reply