I am using Magento 2.4 and I want to add a custom admin Grid for company products. The problem is that I get a an error when I want to perform a mass delete action. The problem appears in my action
MassDelete.php
<?php
declare(strict_types=1);
namespace MyDomain\BestSelling\Controller\Adminhtml\Products;
use Exception;
use Magento\Backend\App\Action;
use Magento\Backend\Model\View\Result\Redirect;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Controller\ResultFactory;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Exception\LocalizedException;
use Magento\Ui\Component\MassAction\Filter;
use MyDomain\BestSelling\Api\MyProductRepositoryInterface;
use MyDomain\BestSelling\Model\ResourceModel\Products\Grid\CollectionFactory as MyProductsFactory;
Use MyDomain\BestSelling\Model\Products\MyProduct as MyProductModel;
use MyDomain\BestSelling\Model\ResourceModel\Products\MyProduct as MyProductRessource;
use Psr\Log\LoggerInterface;
class MassDelete extends Action implements HttpPostActionInterface
{
/**
* @var Filter
*/
protected $filter;
/**
* @var MyProductsFactory
*/
protected $collectionFactory;
/**
* @var MyProductRessource
*/
private $ressource;
/**
* @var MyProductRepositoryInterface
*/
protected $productRepository;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @param Context $context
* @param Filter $filter
* @param MyProductsFactory $collectionFactory
*/
public function __construct(
Context $context,
Filter $filter,
MyProductsFactory $collectionFactory,
MyProductRessource $ressource,
LoggerInterface $logger,
MyProductRepositoryInterface $productRepository
)
{
parent::__construct($context);
$this->productRepository = $productRepository;
$this->filter = $filter;
$this->collectionFactory = $collectionFactory;
$this->ressource = $ressource;
$this->logger = $logger;
}
/**
* Execute action
*
* @return Redirect
* @throws LocalizedException|Exception
*/
public function execute()
{
$collection = $this->filter->getCollection($this->collectionFactory->create());
$collectionSize = $collection->getSize();
foreach ($collection->getItems() as $product) {
try {
$this->productRepository->delete($product);
} catch (LocalizedException $exception) {
$this->logger->error($exception->getLogMessage());
}
$this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', $collectionSize));
/** @var Redirect $resultRedirect */
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
return $resultRedirect->setPath('*/*/');
}
}
}
In the the execute() method I am trying to delete the products with $this->productRepository->delete($product);
but then I am getting the error message:
TypeError: Argument 1 passed to MyDomain\BestSelling\Model\Products\MyProductRepository::delete() must be an instance of MyDomain\BestSelling\Api\Data\MyProductInterface, instance of Magento\Framework\View\Element\UiComponent\DataProvider\Document given
Could it be that my Data Provider doesnt provide what I actually need? Here are my configurations:
UI-Component: best_selling_products_listing.xml
<listing 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">best_selling_products_listing.best_selling_products_listing_data_source
</item>
<item name="deps"
xsi:type="string">best_selling_products_listing.best_selling_products_listing_data_source
</item>
</item>
<item name="spinner" xsi:type="string">spinner_columns</item>
<item name="buttons" xsi:type="array">
<item name="add" xsi:type="array">
<item name="name" xsi:type="string">add</item>
<item name="label" xsi:type="string" translate="true">Add New Post</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/addproduct</item>
</item>
</item>
</argument>
<dataSource name="best_selling_products_listing_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class"
xsi:type="string">Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider
</argument>
<argument name="name" xsi:type="string">best_selling_products_listing_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
<item name="update_url" xsi:type="url" path="mui/index/render"/>
<item name="storageConfig" xsi:type="array">
<item name="indexField" xsi:type="string">id</item>
</item>
</item>
</argument>
</argument>
</dataSource>
<listingToolbar name="listing_top">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="sticky" xsi:type="boolean">true</item>
</item>
</argument>
<bookmark name="bookmarks"/>
<columnsControls name="columns_controls"/>
<exportButton name="export_button"/>
<filters name="listing_filters" />
<filterSearch name="fulltext"/>
<massaction name="listing_massaction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item>
</item>
</argument>
<action name="delete">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">delete</item>
<item name="label" xsi:type="string" translate="true">Delete</item>
<item name="url" xsi:type="url" path="best_selling/products/massDelete"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Post</item>
<item name="message" xsi:type="string" translate="true">Are you sure you wan't to delete selected items?</item>
</item>
</item>
</argument>
</action>
</massaction>
<paging name="listing_paging"/>
</listingToolbar>
<columns name="spinner_columns">
<selectionsColumn name="ids">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="resizeEnabled" xsi:type="boolean">false</item>
<item name="resizeDefaultWidth" xsi:type="string">55</item>
<item name="indexField" xsi:type="string">id</item>
</item>
</argument>
</selectionsColumn>
<column name="id">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">textRange</item>
<item name="sorting" xsi:type="string">asc</item>
<item name="label" xsi:type="string" translate="true">ID</item>
</item>
</argument>
</column>
<column name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">text</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
<item name="label" xsi:type="string" translate="true">Name</item>
</item>
</argument>
</column>
<column name="price">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="editor" xsi:type="array">
<item name="editorType" xsi:type="string">text</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
<item name="label" xsi:type="string" translate="true">Price</item>
</item>
</argument>
</column>
</columns>
<button name="my_new_button">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="actions" xsi:type="array">
<!-- Add your button's actions here -->
<item name="0" xsi:type="array">
<item name="targetName" xsi:type="string">TARGET_NAME</item>
<item name="actionName" xsi:type="string">ACTION_NAME</item>
</item>
</item>
</item>
</argument>
<settings>
<displayAsLink>false</displayAsLink>
<title><![CDATA[Test Button]]></title>
</settings>
</button>
</listing>
Layout: best_selling_products_index.xml
<?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">
<update handle="styles"/>
<body>
<referenceContainer name="content">
<uiComponent name="best_selling_products_listing"/>
</referenceContainer>
</body>
</page>
Dependencies: di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="best_selling_products_listing_data_source" xsi:type="string">MyDomain\BestSelling\Model\ResourceModel\Products\Grid\Collection</item>
</argument>
</arguments>
</type>
<virtualType name="MyDomain\BestSelling\Model\ResourceModel\Products\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
<arguments>
<argument name="mainTable" xsi:type="string">mydomain_bestselling_my_products</argument>
<argument name="resourceModel" xsi:type="string">MyDomain\BestSelling\Model\ResourceModel\Products\MyProduct</argument>
</arguments>
</virtualType>
</config>
Collection: Collection.php
<?php
declare(strict_types=1);
namespace MyDomain\BestSelling\Model\ResourceModel\Products\Grid;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use MyDomain\BestSelling\Model\Products\MyProduct as MyProductModel;
use MyDomain\BestSelling\Model\ResourceModel\Products\MyProduct as MyProductResource;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init(MyProductModel::class, MyProductResource::class);
}
}