I’m working on creating a custom admin grid in Magento 2 using ui_component
, and fetching data from a custom SQL query. However, the grid is not rendering the data in the UI, even though I can see the data is fetched correctly in the logs. I suspect there might be an issue with my di.xml
, dataSource
configuration, or the DataProvider
. Here’s the relevant code:
app/code/Vendor/TargetedList/etc/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- Define the collection factory to be injected into the DataProvider -->
<type name="VendorTargetedListUiComponentDataProvider">
<arguments>
<argument name="collectionFactory" xsi:type="object">VendorTargetedListModelResourceModelCustomCollectionFactory</argument>
</arguments>
</type>
</config>
app/code/Vendor/TargetedList/view/adminhtml/ui_component/custom_grid.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">vendor_targetedlist_custom.custom_data_source</item>
</item>
<item name="spinner" xsi:type="string">custom_columns</item>
</argument>
<dataSource name="custom_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">VendorTargetedListUiComponentDataProvider</argument>
<argument name="name" xsi:type="string">custom_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">entity_id</argument>
</argument>
<settings>
<updateUrl path="mui/index/render"/>
</settings>
</dataSource>
<columns name="custom_columns">
<column name="entity_id">
<settings>
<filter>textRange</filter>
<label translate="true">Order ID</label>
</settings>
</column>
</columns>
</listing>
app/code/Vendor/TargetedList/Model/ResourceModel/Custom/Collection.php
<?php
namespace VendorTargetedListModelResourceModelCustom;
use MagentoFrameworkDataCollection as DataCollection;
class Collection extends DataCollection
{
protected function _construct()
{
// No need to define a table since you're writing a custom SQL query.
}
public function getData()
{
if (!$this->_loadData) {
$this->_renderFilters();
}
$data = [];
foreach ($this as $item) {
$data[] = $item;
}
return $data;
}
public function _initSelect()
{
// Add your custom SQL query here
$this->getSelect()
->from(['so' => $this->getTable('sales_order')], ['entity_id', 'base_grand_total', 'created_at'])
->joinLeft(
['ce' => $this->getTable('customer_entity')],
'so.customer_id = ce.entity_id',
['email', 'firstname', 'lastname']
)
->where('so.base_grand_total > ?', 100);
return $this;
}
}
app/code/Vendor/TargetedList/Model/ResourceModel/Custom/CollectionFactory.php
<?php
namespace VendorTargetedListModelResourceModelCustom;
use MagentoFrameworkObjectManagerInterface;
class CollectionFactory
{
protected $objectManager = null;
protected $instanceName = null;
public function __construct(
ObjectManagerInterface $objectManager,
$instanceName = '\Vendor\TargetedList\Model\ResourceModel\Custom\Collection'
) {
$this->objectManager = $objectManager;
$this->instanceName = $instanceName;
}
public function create(array $data = [])
{
return $this->objectManager->create($this->instanceName, $data);
}
}
app/code/Vendor/TargetedList/Ui/Component/DataProvider.php
<?php
namespace VendorTargetedListUiComponent;
use MagentoUiDataProviderAbstractDataProvider;
use VendorTargetedListModelResourceModelCustomCollectionFactory;
class DataProvider extends AbstractDataProvider
{
protected $_resource;
public function __construct(
MagentoFrameworkAppResourceConnection $resource,
$name,
$primaryFieldName,
$requestFieldName,
CollectionFactory $collectionFactory,
array $meta = [],
array $data = []
) {
$this->collection = $collectionFactory->create();
$this->_resource = $resource;
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
}
public function getData()
{
$connection = $this->_resource->getConnection();
$select = "SELECT so.entity_id, so.base_grand_total, so.created_at, ce.email, ce.firstname, ce.lastname
FROM sales_order AS so
LEFT JOIN customer_entity AS ce ON so.customer_id = ce.entity_id
WHERE so.base_grand_total > 100;";
$items = $connection->fetchAll($select);
MagentoFrameworkAppObjectManager::getInstance()->get('PsrLogLoggerInterface')->debug(print_r($items, true));
return [
'totalRecords' => count($items),
'items' => $items,
];
}
}
Issue:
The custom query seems to be working fine because I can see the expected data in the logs:
[2024-09-09 11:07:23] main.DEBUG: Array
(
[0] => Array
(
[entity_id] => 2535305
[base_grand_total] => 222.8000
[created_at] => 2024-05-03 11:28:14
[email] => [email protected]
[firstname] => Name
[lastname] => Test
)
...
) [] []
However, the data does not show up in the frontend admin grid UI. I have ensured that the column names in custom_grid.xml
match the fields returned from the query (entity_id
, base_grand_total
, created_at
, email
, firstname
, lastname
).
Could the issue be with my dataSource
, di.xml
, or the way the CollectionFactory
is configured? Any help or insights would be greatly appreciated!