I try to turn on inline edit in catalog grid as described in DevDocs:
http://devdocs.magento.com/guides/v2.0/ui-components/ui-secondary-inline.html
The main problem is how to override this block of configuration in
\vendor\magento\module-catalog\view\adminhtml\ui_component\product_listing.xml
<item name="childDefaults" xsi:type="array">
<item name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">product_listing.product_listing.product_columns.actions</item>
<item name="target" xsi:type="string">applyAction</item>
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">edit</item>
<item name="1" xsi:type="string">${ $.$data.rowIndex }</item>
</item>
</item>
</item>
with custom "params" required for inline edit in
\app\code\MyVendor\MyModule\view\adminhtml\ui_component\product_listing.xml
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
<item name="1" xsi:type="boolean">true</item>
</item>
It throws error while loading configuration by the core framework function
**Magento\Ui\Model\Manager->evaluateComponentArguments()**
I don't know how to cure it except overriding framework components such as
Magento\Ui\Model\Manager or Magento\Framework\View\Layout\Generator\UiComponent,
but it's a bad idea
Another decision is to comment "fieldAction" item in the original Magento product_listing.xml
With this modification inline edit works.
Here is the full sample code :
\app\code\MyVendor\MyModule\etc\adminhtml\di.xml
<preference for="Magento\Catalog\Ui\Component\Listing\Columns" type="MyVendor\MyModule\Magento\Catalog\Ui\Component\Listing\Columns" />
\app\code\MyVendor\MyModule\etc\adminhtml\routes.xml
<router id="admin">
<route id="my_product" frontName="my_product">
<module name="MyVendor_MyModule"/>
</route>
</router>
Modified original magento config:
\vendor\magento\module-catalog\view\adminhtml\ui_component\product_listing.xml
------
<item name="childDefaults" xsi:type="array">
<!--<item name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">product_listing.product_listing.product_columns.actions</item>
<item name="target" xsi:type="string">applyAction</item>
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">edit</item>
<item name="1" xsi:type="string">${ $.$data.rowIndex }</item>
</item>
</item>-->
</item>
--------
Custom config:
\app\code\MyVendor\MyModule\view\adminhtml\ui_component\product_listing.xml
<dataSource name="product_listing_data_source"></dataSource>
<listingToolbar name="listing_top"></listingToolbar>
<columns name="product_columns" class="Magento\Customer\Ui\Component\Listing\Columns">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editorConfig" xsi:type="array">
<item name="selectProvider" xsi:type="string">product_listing.product_listing.product_columns.ids</item>
<item name="enabled" xsi:type="boolean">true</item>
<item name="indexField" xsi:type="string">entity_id</item>
<item name="clientConfig" xsi:type="array">
<item name="saveUrl" xsi:type="url" path="my_product/product/inlineEdit"/>
<item name="validateBeforeSave" xsi:type="boolean">false</item>
</item>
</item>
<item name="childDefaults" xsi:type="array">
<item 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>
</item>
</item>
</item>
</argument>
<column name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editor" xsi:type="string">text</item>
</item>
</argument>
</column>
<column name="my_pku">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="editor" xsi:type="string">text</item>
</item>
</argument>
</column>
----- other columns ----
</columns>
\app\code\MyVendor\MyModule\Controller\Adminhtml\Product.php
namespace MyVendor\MyModule\Controller\Adminhtml;
use Magento\Backend\App\Action;
abstract class Product extends \Magento\Backend\App\Action {
const ADMIN_RESOURCE = 'Magento_Catalog::products';
public function __construct(
\Magento\Backend\App\Action\Context $context
) {
parent::__construct($context);
}
}
\app\code\MyVendor\MyModule\Controller\Adminhtml\Product\InlineEdit.php
namespace MyVendor\MyModule\Controller\Adminhtml\Product;
use Magento\Backend\App\Action;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
class InlineEdit extends \Magento\Backend\App\Action {
const ADMIN_RESOURCE = 'Magento_Catalog::products';
private $product;
protected $productRepository;
protected $resultJsonFactory;
protected $dataObjectHelper;
protected $logger;
public function __construct(
Action\Context $context, ProductRepositoryInterface $productRepository,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
\Psr\Log\LoggerInterface $logger
) {
$this->productRepository = $productRepository;
$this->resultJsonFactory = $resultJsonFactory;
$this->dataObjectHelper = $dataObjectHelper;
$this->logger = $logger;
parent::__construct($context);
}
public function execute() {
$resultJson = $this->resultJsonFactory->create();
$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 $productId => $productRow) {
$this->setProduct($this->productRepository->getById($productId));
$data = $this->product->getData();
// ---- formatting and validating
// $this->my_server_side_validator($data);
// $this->my_server_side_formatter($data);
// saving
$dataUpdated = array_replace($data, $productRow);
$this->product->setData($dataUpdated);
$this->product->save();
}
return $resultJson->setData([
'messages' => $this->getErrorMessages(),
'error' => $this->isErrorExists()
]);
}
protected function getErrorMessages() {
$messages = [];
foreach ($this->getMessageManager()->getMessages()->getItems() as $error) {
$messages[] = $error->getText();
}
return $messages;
}
protected function isErrorExists() {
return (bool) $this->getMessageManager()->getMessages(true)->getCount();
}
protected function setProduct(ProductInterface $product) {
$this->product = $product;
return $this;
}
protected function getProduct() {
return $this->product;
}
}
\app\code\MyVendor\MyModule\Magento\Catalog\Ui\Component\Listing\Columns.php
namespace MyVendor\MyModule\Magento\Catalog\Ui\Component\Listing;
class Columns extends \Magento\Catalog\Ui\Component\Listing\Columns {
// Array of attributes not included in
// \vendor\magento\module-catalog\view\adminhtml\ui_component\product_listing.xml
protected $additional_fields = [
'my_pku'
];
public function __construct(
\Magento\Framework\View\Element\UiComponent\ContextInterface $context,
\Magento\Catalog\Ui\Component\ColumnFactory $columnFactory,
\Magento\Catalog\Ui\Component\Listing\Attribute\RepositoryInterface $attributeRepository,
array $components = [], array $data = []
) {
parent::__construct($context, $columnFactory, $attributeRepository,
$components, $data);
}
/**
* {@inheritdoc}
*/
public function prepare() {
$columnSortOrder = self::DEFAULT_COLUMNS_MAX_ORDER;
foreach ($this->attributeRepository->getList() as $attribute) {
$attr_code = $attribute->getAttributeCode();
$config = [];
if (!isset($this->components[$attr_code]) || in_array($attr_code,
$this->additional_fields)) {
$config['sortOrder'] = ++$columnSortOrder;
if ($attribute->getIsFilterableInGrid()) {
$config['filter'] = $this->getFilterType($attribute->getFrontendInput());
}
// Copy editor configuration for additional attributes
if (isset($this->components[$attr_code]->_data['config']['editor'])) {
$config['editor'] = $this->components[$attr_code]->_data['config']['editor'];
}
$column = $this->columnFactory->create($attribute,
$this->getContext(), $config);
$column->prepare();
$this->addComponent($attribute->getAttributeCode(), $column);
}
}
parent::prepare();
}
}
I need to extend Column.php because custom product_listing.xml also can't add editor config for additional product attributes like "my_pku" code, that not included in original Magento product_listing.xml
Without this, I can inline edit only predefined fields in original Magento product_listing.xml
So, QUESTIONS are:
-
How to enable catalog inline edit without modifying \vendor\magento\module-catalog\view\adminhtml\ui_component\product_listing.xml ?
-
What is an acceptable method to replace original ui_component config XML files safely, when item types are different?
UPDATE:
to Pramod Kumar Sharma
In 2.1.6
I had to comment out this block of code in
\vendor\magento\module-catalog\view\adminhtml\ui_component\product_listing.xml
------
<item name="childDefaults" xsi:type="array">
<!--<item name="fieldAction" xsi:type="array">
<item name="provider" xsi:type="string">product_listing.product_listing.product_columns.actions</item>
<item name="target" xsi:type="string">applyAction</item>
<item name="params" xsi:type="array">
<item name="0" xsi:type="string">edit</item>
<item name="1" xsi:type="string">${ $.$data.rowIndex }</item>
</item>
</item>-->
</item>
--------
In 2.2.1
it works without commenting out.
I have no separate extension for this, it's part of my module with many other improvements
Just do as described above
Best Answer
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
Step 2 Remove cursor over the fields
Add css file in below path:-
Step 3 Inline edit fields with the use of plugin method
Create plugin file in path :-
Step 4 Create js file to control columns
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:-
Create controller file in below path :-