If you want to add a new record or edit an existing record, it is possible to create a form to have a user friendly way to process the data. In this example, we will see how to create a form to edit an existing record. The path used to add a record will be as follows:
http://example.com/admin/sample/demolist/new/
This will require the controller name to be new, but as this is a reserved word in PHP, the class name used will be newAction. The execute function is not only used to add a new record, but it can also be used to edit an existing record. In the following code, only the execute action is shown; see the sample code for the complete source.
In this recipe, we will add the option to add or edit records; for this, the route used in the previous chapter is used, only new controllers and blocks are shown.
Follow these steps to add a form to your module:
Controller/Adminhtml/Demolist/NewAction.php
<?php
namespace Genmato\Sample\Controller\Adminhtml\Demolist;
use Magento\Backend\App\Action;
class NewAction extends Action
{
public function execute()
{
$demoId = $this->getRequest()->getParam('demo_id');
$this->_coreRegistry->register('current_demo_id', $demoId);
/** @var \Magento\Backend\Model\View\Result\Page $resultPage */
$resultPage = $this->resultPageFactory->create();
if ($demoId === null) {
$resultPage->addBreadcrumb(__('New DemoList'), __('New DemoList'));
$resultPage->getConfig()->getTitle()->prepend(__('New DemoList'));
} else {
$resultPage->addBreadcrumb(__('Edit DemoList'), __('Edit DemoList'));
$resultPage->getConfig()->getTitle()->prepend(__('Edit DemoList'));
}
// Build the edit form
$resultPage->getLayout()->addBlock('Genmato\Sample\Block\Adminhtml\Demo\Edit', 'demolist', 'content')
->setEditMode((bool)$demoId);
return $resultPage;
}
}Form container:Block/Adminhtml/Demo/Edit.php
<?php
namespace Genmato\Sample\Block\Adminhtml\Demo;
use Magento\Backend\Block\Widget\Form\Container;
class Edit extends Container
{
/**
* Remove Delete button if record can't be deleted.
*
* @return void
*/
protected function _construct()
{
$this->_objectId = 'demo_id';
$this->_controller = 'adminhtml_demo';
$this->_blockGroup = 'Genmato_Sample';
parent::_construct();
$demoId = $this->getDemoId();
if (!$demoId) {
$this->buttonList->remove('delete');
}
}
/**
* Retrieve the header text, either editing an existing record or creating a new one.
*
* @return \Magento\Framework\Phrase
*/
public function getHeaderText()
{
$demoId = $this->getDemoId();
if (!$demoId) {
return __('New DemoList Item');
} else {
return __('Edit DemoList Item');
}
}
public function getDemoId()
{
if (!$this->demoId) {
$this->demoId=$this->coreRegistry->registry('current_demo_id');
}
return $this->demoId;
}
}Block/Adminhtml/Demo/Edit/Form.php
<?php
namespace Genmato\Sample\Block\Adminhtml\Demo\Edit;
use Magento\Customer\Controller\RegistryConstants;
use Magento\Backend\Block\Widget\Form\Generic;
class Form extends Generic
{
/**
* Prepare form for render
*
* @return void
*/
protected function _prepareLayout()
{
parent::_prepareLayout();
/** @var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$demoId = $this->_coreRegistry->registry('current_demo_id');
/** @var \Genmato\Sample\Model\DemoFactory $demoData */
if ($demoId === null) {
$demoData = $this->demoDataFactory->create();
} else {
$demoData = $this->demoDataFactory->create()->load($demoId);
}
$yesNo = [];
$yesNo[0] = 'No';
$yesNo[1] = 'Yes';
$fieldset = $form->addFieldset('base_fieldset', ['legend' => __('Basic Information')]);
$fieldset->addField(
'title',
'text',
[
'name' => 'title',
'label' => __('Title'),
'title' => __('Title'),
'required' => true
]
);
$fieldset->addField(
'is_active',
'select',
[
'name' => 'is_active',
'label' => __('Active'),
'title' => __('Active'),
'class' => 'required-entry',
'required' => true,
'values' => $yesNo,
]
);
$fieldset->addField(
'is_visible',
'select',
[
'name' => 'is_visible',
'label' => __('Visible'),
'title' => __('Visible'),
'class' => 'required-entry',
'required' => true,
'values' => $yesNo,
]
);
if ($demoData->getId() !== null) {
// If edit add id
$form->addField('demo_id', 'hidden', ['name' => 'demo_id', 'value' => $demoData->getId()]);
}
if ($this->_backendSession->getDemoData()) {
$form->addValues($this->_backendSession->getDemoData());
$this->_backendSession->setDemoData(null);
} else {
$form->addValues(
[
'id' => $demoData->getId(),
'title' => $demoData->getTitle(),
'is_active' => $demoData->getIsActive(),
'is_visible' => $demoData->getIsVisible(),
]
);
}
$form->setUseContainer(true);
$form->setId('edit_form');
$form->setAction($this->getUrl('*/*/save'));
$form->setMethod('post');
$this->setForm($form);
}
}Save action controller, which is called when pressing the Submit button:Controller/Adminhtml/Demolist/Save.php
<?php
namespace Genmato\Sample\Controller\Adminhtml\Demolist;
use Magento\Backend\App\Action;
class Save extends Action
{
/**
* Save DemoList item.
*
* @return \Magento\Backend\Model\View\Result\Page|\Magento\Backend\Model\View\Result\Redirect
*/
public function execute()
{
$id = $this->getRequest()->getParam('demo_id');
$resultRedirect = $this->resultRedirectFactory->create();
try {
if ($id !== null) {
$demoData = $this->demoFactory->create()->load((int)$id);
} else {
$demoData = $this->demoFactory->create();
}
$data = $this->getRequest()->getParams();
$demoData->setData($data)->save();
$this->messageManager->addSuccess(__('Saved DemoList item.'));
$resultRedirect->setPath('sample/demolist');
} catch (\Exception $e) {
$this->messageManager->addError($e->getMessage());
$this->_getSession()->setDemoData($data);
$resultRedirect->setPath('sample/demolist/edit', ['demo_id' => $id]);
}
return $resultRedirect;
}
}In the controller, the demo_id parameter is stored in the Magento registry; this makes the data available to retrieve in the same request in other blocks/models to do further processing with it. Additionally, the Genmato\Sample\Block\Adminhtml\Demo\Edit class is loaded. This class will generate the container for the form and load the Genmato\Sample\Block\Adminhtml\Demo\Edit\Form class that will generate the form to be shown.
Every form is built from the following:
$form = $this->_formFactory->create();
As it is not possible to add fields to a form directly, you need to create a fieldset first. It is possible to add multiple fieldsets to a single form and assign multiple form fields to a fieldset. To create a fieldset, use the following command:
$fieldset = $form->addFieldset('[name]', ['legend' => __([heading])]);Adding a form field to the fieldset is done as follows:
$fieldset->addField([elementId], [type], [config], [after]);
This method has the following parameters:
elementId: This is the unique name of the form field element.type: This defines the type of element that is used as the input field. This can be your own class that implements the Magento\Framework\Data\Form\Element\AbstractElement class or one of the following:These input types are rendered from the classes found under the Magento\Framework\Data\Form\Element\ directory.
config: This is an array of extra configuration data; some of the options are as follows:name: This is the name of the element from the data model that holds the datalabel: This is the text that is used as a labeltitle: This is the text that is used as the field title parameterclass: This is the optional class for the input field, which can be used for form validationrequired: This is optional. This is set if a field is required to have data.value: This is the value used for select/multiselectafter: This is the optional parameter to specify where the form field needs to be placed; use elementId of the form field that you want to place this field after.In order to display the data currently stored for the record that we want to edit, the stored demo_id is retrieved from the registry:
$demoId = $this->_coreRegistry->registry('current_demo_id');Next, we check whether there is a valid value stored as demoId and load the data from the database (or just set an empty object):
/** @var \Genmato\Sample\Model\DemoFactory $demoData */
if ($demoId === null) {
$demoData = $this->demoDataFactory->create();
} else {
$demoData = $this->demoDataFactory->create()->load($demoId);
}Now that the data is loaded, it is possible to set this data to the form fields:
$form->addValues(
[
'id' => $demoData->getId(),
'title' => $demoData->getTitle(),
'is_active' => $demoData->getIsActive(),
'is_visible' => $demoData->getIsVisible(),
]
);When submitting the form to save the data, the action and method should be set to the URL that handles the save action:
$form->setAction($this->getUrl('*/*/save'));
$form->setMethod('post');The URL */*/save maps to the Controller/Adminhtml/Demolist/Save controller and will handle the save action.
In the controller, we first load the current record to load all the current values:
if ($id !== null) {
$demoData = $this->demoFactory->create()->load((int)$id);
} else {
$demoData = $this->demoFactory->create();
}Next, we retrieve the submitted data, store it in the loaded object, and save the object:
$data = $this->getRequest()->getParams(); $demoData->setData($data)->save();