Can you please briefly explain how inline edit work in admin ui-components grid in Magento2.
Please explain controller
, interface
, and model
.
gridinline-editormagento2uicomponent
Can you please briefly explain how inline edit work in admin ui-components grid in Magento2.
Please explain controller
, interface
, and model
.
I have found the way for it. I have overridden all the files.I have done inline edit for below attributes.
-- brand, sku, name, price, visibility, status
Also i have done it for below custom dropdown attributes which are
-- supplier , show on home page or not(boolean)
Please follow below steps
Step 1 Show attributes in grid
PackageName/ProductInlineEdit/view/adminhtml/ui_component/product_listing.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction" component="Magento_Ui/js/grid/tree-massactions" class="\Magento\Catalog\Ui\Component\Product\MassAction">
<action name="edit">
<settings>
<callback>
<target>editSelected</target>
<provider>product_listing.product_listing.product_columns_editor</provider>
</callback>
<type>edit</type>
<label translate="true">Edit</label>
</settings>
</action>
</massaction>
</listingToolbar>
<columns name="product_columns" class="Magento\Catalog\Ui\Component\Listing\Columns">
<settings>
<editorConfig>
<param name="clientConfig" xsi:type="array">
<item name="saveUrl" xsi:type="url" path="productinlineedit/product/inlineEdit"/>
<item name="validateBeforeSave" xsi:type="boolean">false</item>
</param>
<param name="indexField" xsi:type="string">entity_id</param>
<param name="enabled" xsi:type="boolean">true</param>
<param name="selectProvider" xsi:type="string">product_listing.product_listing.product_columns.ids</param>
</editorConfig>
<childDefaults>
<param name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">product_listing.product_listing.product_columns_editor</item>
<item name="target" xsi:type="string">startEdit</item>
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
<item name="1" xsi:type="boolean">true</item>
</item>
</param>
</childDefaults>
</settings>
<column name="name" sortOrder="30">
<settings>
<editor>
<editorType>text</editorType>
</editor>
</settings>
</column>
<column name="sku" sortOrder="60">
<settings>
<editor>
<editorType>text</editorType>
</editor>
</settings>
</column>
<column name="price" class="Magento\Catalog\Ui\Component\Listing\Columns\Price" sortOrder="70">
<settings>
<editor>
<editorType>text</editorType>
</editor>
</settings>
</column>
<column name="visibility" component="Magento_Ui/js/grid/columns/select" sortOrder="80">
<settings>
<editor>
<editorType>select</editorType>
</editor>
</settings>
</column>
<column name="status" component="Magento_Ui/js/grid/columns/select" sortOrder="90">
<settings>
<editor>
<editorType>select</editorType>
</editor>
</settings>
</column>
</columns>
</listing>
Step 2 Remove cursor over the fields
PackageName/ProductInlineEdit/view/adminhtml/layout/default.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="PackageName_ProductInlineEdit::css/inlineedit.css"/>
</head>
</page>
Add css file in below path:-
PackageName/ProductInlineEdit/view/adminhtml/web/css/inlineedit.css
.catalog-product-index .admin__data-grid-wrap .data-row{cursor: default !important;}
Step 3 Inline edit fields with the use of plugin method
PackageName/ProductInlineEdit/etc/adminhtml/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Ui\Component\ColumnFactory">
<plugin name="packagename.product.inlineedit" type="PackageName\ProductInlineEdit\Plugin\Component\Listing\ColumnFactory" sortOrder="10" disabled="false" />
</type>
</config>
Create plugin file in path :-
PackageName\ProductInlineEdit\Plugin\Component\Listing\ColumnFactory
<?php
namespace PackageName\ProductInlineEdit\Plugin\Component\Listing;
/**
* {@inheritdoc}
*/
class ColumnFactory {
/**
* @var array
*/
protected $editorMap = [
'default' => 'text',
'select' => 'select',
'boolean' => 'select',
'multiselect' => 'select',
'date' => 'dateRange',
];
/**
* Add Inline Edit for custom Attributes
*
* @param $subject
* @param $attribute
* @param $context
* @param $config
*/
public function beforeCreate(\Magento\Catalog\Ui\Component\ColumnFactory $subject, $attribute, $context, array $config = [])
{
$editorType = $attribute->getFrontendInput();
if(isset($this->editorMap[$editorType])){
$editorType = $this->editorMap[$editorType];
}
$config['editor'] = ['editorType'=> $editorType];
return [$attribute, $context, $config];
}
}
Step 4 Create js file to control columns
PackageName/ProductInlineEdit/view/adminhtml/requirejs-config.js
var config =
{
map:
{
'*':
{
'Magento_Ui/js/grid/controls/columns':'PackageName_ProductInlineEdit/js/grid/controls/columns'
}
}
};
PackageName/ProductInlineEdit/view/adminhtml/web/js/grid/controls/columns.js
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* @api
*/
define([
'underscore',
'mageUtils',
'mage/translate',
'uiCollection'
], function (_, utils, $t, Collection) {
'use strict';
return Collection.extend({
defaults: {
template: 'ui/grid/controls/columns',
minVisible: 1,
maxVisible: 30,
viewportSize: 18,
displayArea: 'dataGridActions',
columnsProvider: 'ns = ${ $.ns }, componentType = columns',
imports: {
addColumns: '${ $.columnsProvider }:elems'
},
templates: {
headerMsg: $t('${ $.visible } out of ${ $.total } visible')
}
},
/**
* Resets columns visibility to theirs default state.
*
* @returns {Columns} Chainable.
*/
reset: function () {
this.elems.each('applyState', 'default', 'visible');
return this;
},
/**
* Applies last saved state of columns visibility.
*
* @returns {Columns} Chainable.
*/
cancel: function () {
//this.elems.each('applyState', '', 'visible');
return this;
},
/**
* Adds columns whose visibility can be controlled to the component.
*
* @param {Array} columns - Elements array that will be added to component.
* @returns {Columns} Chainable.
*/
addColumns: function (columns) {
columns = _.where(columns, {
controlVisibility: true
});
this.insertChild(columns);
return this;
},
/**
* Defines whether child elements array length
* is greater than the 'viewportSize' property.
*
* @returns {Boolean}
*/
hasOverflow: function () {
return this.elems().length > this.viewportSize;
},
/**
* Helper, checks
* - if less than one item choosen
* - if more then viewportMaxSize choosen
*
* @param {Object} elem
* @returns {Boolean}
*/
isDisabled: function (elem) {
var visible = this.countVisible();
return elem.visible ?
visible === this.minVisible :
visible === this.maxVisible;
},
/**
* Counts number of visible columns.
*
* @returns {Number}
*/
countVisible: function () {
return this.elems.filter('visible').length;
},
/**
* Compile header message from headerMessage setting.
*
* @returns {String}
*/
getHeaderMessage: function () {
return utils.template(this.templates.headerMsg, {
visible: this.countVisible(),
total: this.elems().length
});
}
});
});
Step 5 Save inline data with the use of custom controller. We have already defined controller path in product_listing.xml file
Create router file to define controller name:-
PackageName/ProductInlineEdit/etc/adminhtml/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="productinlineedit" frontName="productinlineedit">
<module name="PackageName_ProductInlineEdit" />
</route>
</router>
</config>
Create controller file in below path :-
PackageName/ProductInlineEdit/Controller/Adminhtml/Product/InlineEdit.php
<?php
namespace PackageName\ProductInlineEdit\Controller\Adminhtml\Product;
class InlineEdit extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Framework\Controller\Result\JsonFactory
*/
protected $jsonFactory;
/**
* @var \Magento\Catalog\Model\ProductFactory $productFactory
*/
protected $productFactory;
/**
* @param \Magento\Backend\App\Action\Context $context
* @param \Magento\Framework\Controller\Result\JsonFactory $jsonFactory
* @param \Magento\Catalog\Model\ProductFactory $productFactory
*/
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $jsonFactory,
\Magento\Catalog\Model\ProductFactory $productFactory
) {
parent::__construct($context);
$this->jsonFactory = $jsonFactory;
$this->_productFactory = $productFactory;
}
/**
* @return \Magento\Framework\Controller\Result\JsonFactory
*/
public function execute()
{
$resultJson = $this->jsonFactory->create();
$error = false;
$messages = [];
$postItems = $this->getRequest()->getParam('items', []);
if (!($this->getRequest()->getParam('isAjax') && count($postItems))) {
return $resultJson->setData([
'messages' => [__('Please correct the data sent.')],
'error' => true,
]);
}
foreach ($postItems as $value)
{
if ($value) {
$productObj = $this->_productFactory->create();
if ($value['entity_id']) {
$productObj->load($value['entity_id']);
}
$productObj->setStoreId(0);
if(array_key_exists('name', $value)) {
$productObj->setName($value['name']);
}
if(array_key_exists('sku', $value)) {
$productObj->setSku($value['sku']);
}
if(array_key_exists('price', $value)) {
$productObj->setPrice($value['price']);
}
if(array_key_exists('visibility', $value)) {
$productObj->setVisibility($value['visibility']);
}
if(array_key_exists('status', $value)) {
$productObj->setStatus($value['status']);
}
if(array_key_exists('brand', $value)) {
$productObj->setBrand($value['brand']);
}
if(array_key_exists('showinhome', $value)) {
$productObj->setShowinhome($value['showinhome']);
}
if(array_key_exists('supplier_id', $value)) {
$productObj->setSupplierId($value['supplier_id']);
}
try {
$productObj->save();
} catch (\Magento\Framework\Model\Exception $e) {
$this->messageManager->addError($e->getMessage());
}
}
}
return $resultJson->setData([
'messages' => $messages,
'error' => $error
]);
}
}
First you can use this block use in our UI components xml Files.
<item name="buttons" xsi:type="array">
<item name="back" xsi:type="string">vendor\ProductComments\Block\Adminhtml\Index\Edit\Button\Back</item>
<item name="delete" xsi:type="string">vendor\ProductComments\Block\Adminhtml\Index\Edit\Button\Delete</item>
<item name="reset" xsi:type="string">vendor\ProductComments\Block\Adminhtml\Index\Edit\Button\Reset</item>
<item name="save" xsi:type="string">vendor\ProductComments\Block\Adminhtml\Index\Edit\Button\Save</item>
<item name="save_and_continue" xsi:type="string">vendor\ProductComments\Block\Adminhtml\Index\Edit\Button\SaveAndContinue</item>
</item>
Then you can open save and continue block open and can you use this code
public function getButtonData() {
return [
'label' => __('Save and Continue Edit'),
'class' => 'save',
'data_attribute' => [
'mage-init' => [
'button' => ['event' => 'saveAndContinueEdit'],
],
],
'sort_order' => 80,
];
We also faced this issue, This code working you can use it.
Best Answer
There are two main files for inline edit in admin grid
1) Ui Component Grid
2) Contoller for save data
Let's take an example
vendor: Test
andmodule name: Test
In the following sample code, I have created a UI Component file named
test_mytesting_index.xml
atapp/code/Test/Test/view/adminhtml/ui_component/test_mytesting_index.xml
Here you need to pass inline controller to edit inline data
<item name="saveUrl" path="test_test/mytesting/inlineEdit" xsi:type="url"/>
Now create controller
InlineEdit.php
to get the posted data and save it into the databaseThe action inlineEdit will save the data into mysql. We will make the grid clickable by the element fieldAction
We will make the column editable inline by using the element editor:
In the configuration for the specific column, the editor can include:
editorType - type of the editor. Possible values: same as primitives (text, select, date), can also provide new type.
validation - validation rules, required-entry here as just an example of possible rules