1. Create a new Module, named: Jeff_Contacts
I will use the contact information as an example to show you how to create backend UiComponent grid list and UiComponent Edit Form. First we need to create the basic Magento 2 module:
module.xml file:
registration.php file:
Setup Script, InstallSchema.php:
The database table structure is like as following:startSetup(); //START: install stuff //END: install stuff //START table setup $table = $installer->getConnection()->newTable( $installer->getTable('jeff_contacts_contact') )->addColumn( 'jeff_contacts_contact_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, [ 'identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true, ], 'Entity ID' )->addColumn( 'name', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 255, [ 'nullable' => false, ], 'Demo name' )->addColumn( 'email', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 255, [ 'nullable' => false, ], 'Demo email' )->addColumn( 'comment', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 255, [ 'nullable' => false, 'default' => '0' ], 'Demo comment' )->addColumn( 'creation_time', \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT, ], 'Creation Time' )->addColumn( 'update_time', \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE, ], 'Modification Time' )->addColumn( 'is_active', \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, null, [ 'nullable' => false, 'default' => '1', ], 'Is Active' ); $installer->getConnection()->createTable($table); //END table setup $installer->endSetup(); } }
+--------------------------+------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +--------------------------+------------------+------+-----+-------------------+-----------------------------+ | jeff_contacts_contact_id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | email | varchar(255) | NO | | NULL | | | comment | varchar(255) | NO | | 0 | | | creation_time | timestamp | NO | | CURRENT_TIMESTAMP | | | update_time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | | is_active | smallint(6) | NO | | 1 | | +--------------------------+------------------+------+-----+-------------------+-----------------------------+
Contact model:
_init('Jeff\Contacts\Model\ResourceModel\Contact'); } public function getIdentities() { return [self::CACHE_TAG . '_' . $this->getId()]; } }
ResourceModel for Contact
_init('jeff_contacts_contact','jeff_contacts_contact_id'); } }
Contact Collection
_init('Jeff\Contacts\Model\Contact','Jeff\Contacts\Model\ResourceModel\Contact'); } }
backend routers.xml:
menu.xml
Index controller file
resultPageFactory = $resultPageFactory; parent::__construct($context); } public function execute() { return $this->resultPageFactory->create(); } }
2 UiComponent Grid List:
backend layout: jeff_contacts_index_index.xml
#app/code/Jeff/Contacts/view/adminhtml/layout/jeff_contacts_index_index.xml
From this layout file, we can find out that we need to generate three more files, backend block file: Main.php and template file for the block: content.phtml and our own uiComponent: contacts_test_listing.xml
Main.php
#app/code/Jeff/Contacts/Block/Adminhtml/Main.php
content.phtml
#app/code/Jeff/Contacts/view/adminhtml/templates/content.html Contacts
uiComponent definition: contacts_test_listing.xml
#app/code/Jeff/Contacts/view/adminhtml/ui_component/contacts_test_listing.xml - contacts_test_listing.contacts_test_listing_data_source
- contacts_test_listing.contacts_test_listing_data_source
- contacts_test_columns
- add
- Add a new Contact
- primary
- */*/newAction
ContactsGridDataProvider contacts_test_listing_data_source jeff_contacts_contact_id id - Magento_Ui/js/grid/provider
- jeff_contacts_contact_id
- contacts_test_listing.contacts_test_listing.listing_top.bookmarks
- current
- true
- contacts_test_listing.contacts_test_listing.listing_top.bookmarks
- columns.${ $.index }
- current.${ $.storageConfig.root}
- jeff_contacts_contact_id
- textRange
- asc
- ID
- true
- text
- input
- contact
- name
- text
- Name
- true
- true
- text
- input
- contact
- text
- true
- true
- text
- input
- contact
- comment
- text
- Comment
- false
- false
- 107
- pfay_contacts_id
This file contains three main sections: configuration, dataProvider and columns. Configuration section: Here we declare the data_source to use with the tag ‘js_config’, which makes the links between your grid and the database.
UiComponent Column for ActionsColumn:
urlBuilder = $urlBuilder; parent::__construct($context, $uiComponentFactory, $components, $data); } public function prepareDataSource(array $dataSource) { if(isset($dataSource['data']['items'])) { foreach($dataSource['data']['items'] as &$item) { $item[$this->getData('name')]['edit'] = [ 'href' => $this->urlBuilder->getUrl('jeff_contacts/index/edit', ['id' => $item['jeff_contacts_contact_id']]), 'label' => __('Edit'), 'hidden' => false ]; $item[$this->getData('name')]['delete'] = [ 'href' => $this->urlBuilder->getUrl('jeff_contacts/index/delete', ['id' => $item['jeff_contacts_contact_id']]), 'label' => __('Delete'), 'hidden' => false ]; } } return $dataSource; } }
Connecting model and grid by creating di.xml
Jeff\Contacts\Model\ResourceModel\Contact\Collection ContactsGridFilterPool - Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter
- Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter
- Jeff\Contacts\Model\ResourceModel\Contact\Grid\Collection
jeff_contacts_contact Jeff\Contacts\Model\ResourceModel\Contact
3 UiComponent edit Form
Create NewAction action file:
resultPageFactory = $resultPageFactory; parent::__construct($context); } public function execute() { return $this->resultPageFactory->create(); } }
handler file for jeff_contacts_index_newaction action
update handler file: jeff_contacts_index_edit.xml
Here, we defined our uiComponent edit file and we will create it next.
uiComponent Form definition
#app/code/Jeff/Contacts/view/adminhtml/ui_component/jeff_contacts_form.xml
Four Button Blocks: Back, Delete, Reset and Save
BackButton.php:
__('Back'), 'on_click' => sprintf("location.href= '%s';", $this->getBackUrl()), 'class' => 'back', 'sort_order' => 10 ]; } public function getBackUrl() { return $this->getUrl('*/*/'); } }
DeleteButton.php:
__('Delete Contact'), 'on_click' => 'deleteConfirm(\'' . __('Are you sure you want to delete this contact ?') . '\', \'' . $this->getDeleteUrl() . '\')', 'class' => 'delete', 'sort_order' => 20 ]; } public function getDeleteUrl() { $urlInterface = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\UrlInterface'); $url = $urlInterface->getCurrentUrl(); $parts = explode('/', parse_url($url, PHP_URL_PATH)); $id = $parts[6]; return $this->getUrl('*/*/delete', ['id' => $id]); } }
ResetButton.php:
__('Reset'), 'on_click' => 'javascript: location.reload();', 'class' => 'reset', 'sort_order' => 30 ]; } }
SaveButton.php:
__('Save Contact'), 'class' => 'save primary', 'data_attribute' => [ 'mage-init' => ['button' => ['event' => 'save']], 'form-role' => 'save', ], //'on_click' => sprintf("location.href= '%s';", $this->getSaveUrl()), 'sort_order' => 90 ]; } public function getSaveUrl() { return $this->getUrl('*/*/save', []) ; } }
data provider file: DataProvider.php
collection = $contactCollectionFactory->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 $contact) { $this->_loadedData[$contact->getId()] = $contact->getData(); } return $this->_loadedData; } }
Edit Controller
resultPageFactory = $resultPageFactory; parent::__construct($context); } public function execute() { return $this->resultPageFactory->create(); } }
Save Controller
resultPageFactory = $resultPageFactory; $this->contactFactory = $contactFactory; parent::__construct($context); } public function execute() { $resultRedirect = $this->resultRedirectFactory->create(); $data = $this->getRequest()->getPostValue(); if($data) { try{ $id = $data['jeff_contacts_contact_id']; $contact = $this->contactFactory->create()->load($id); $data = array_filter($data, function($value) {return $value !== ''; }); $contact->setData($data); $contact->save(); $this->messageManager->addSuccess(__('Successfully saved the item.')); $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false); return $resultRedirect->setPath('*/*/'); } catch(\Exception $d) { $this->messageManager->addError($e->getMessage()); $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData($data); return $resultRedirect->setPath('*/*/edit', ['id' => $contact->getId()]); } } return $resultRedirect->setPath('*/*/'); } }
Delete Controller
resultPageFactory = $resultPageFactory; $this->contactFactory = $contactFactory; parent::__construct($context); } public function execute() { $id = $this->getRequest()->getParam('id'); $contact = $this->contactFactory->create()->load($id); if(!$contact) { $this->messageManager->addError(__('Unable to process. please, try again.')); $resultRedirect = $this->resultRedirectFactory->create(); return $resultRedirect->setPath('*/*/', array('_current' => true)); } try{ $contact->delete(); $this->messageManager->addSuccess(__('Your contact has been deleted !')); } catch(\Exception $e) { $this->messageManager->addError(__('Error while trying to delete contact')); $resultRedirect = $this->resultRedirectFactory->create(); return $resultRedirect->setPath('*/*/index', array('_current' => true)); } $resultRedirect = $this->resultRedirectFactory->create(); return $resultRedirect->setPath('*/*/index', array('_current' => true)); } }
4 Final Results: some images:
You can download the source code at HERE