Magento 2 – store_id in UI Listing Component

magento2store-viewuicomponent

I'm developing a Magento2 extension that has an admin grid which is generated using the UI Listing Component. The grid shows the records (a list of blog items) just fine. The extension allows to save blog items for specific store views which saves the blog_id together with the store_id in a separate database table. Now what I would like to do is show a column in the grid with blog items that shows the store views selected for each blog item.

The whole setup is quite similar to the CMS pages and cms_page_listing.xml. There is a column in my blog_listing.xml for the store view like this:

<column name="store_id" class="Magento\Store\Ui\Component\Listing\Column\Store">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
            <item name="sortable" xsi:type="boolean">false</item>
            <item name="label" xsi:type="string" translate="true">Store View</item>
        </item>
    </argument>
</column>

When loading the grid the following error is shown: "Notice: Undefined index: store_id in ..\vendor\magento\module-store\Ui\Component\Listing\Column\Store.php on line 82"

Obviously there is no store_id in the default collection of the blog items as it's connected through another table with the actual store_id's. But my collection looks like this and it should be in there:
app\code\vendor\module\Model\ResourceModel\AbstractCollection.php

protected function performAfterLoadBlog($tableName, $columnName) {
    $items = $this->getColumnValues($columnName);
    if (count($items)) {
        $connection = $this->getConnection();
        $select = $connection->select()->from(['blog_entity_store' => $this->getTable($tableName)])
            ->where('blog_entity_store.' . $columnName . ' IN (?)', $items);
        $result = $connection->fetchPairs($select);
        if ($result) {
            foreach ($this as $item) {
                $entityId = $item->getData($columnName);
                if (!isset($result[$entityId])) {
                    continue;
                }
                if ($result[$entityId] == 0) {
                    $stores = $this->storeManager->getStores(false, true);
                    $storeId = current($stores)->getId();
                    $storeCode = key($stores);
                } else {
                    $storeId = $result[$item->getData($columnName)];
                    $storeCode = $this->storeManager->getStore($storeId)->getCode();
                }
                $item->setData('_first_store_id', $storeId);
                $item->setData('store_code', $storeCode);
                $item->setData('store_id', [$result[$entityId]]);
            }
        }
    }
}

protected function joinStoreRelationTable($tableName, $columnName) {
        if ($this->getFilter('store')) {
            $this->getSelect()->join(
                ['store_table' => $this->getTable($tableName)],
                'main_table.' . $columnName . ' = store_table.' . $columnName,
                []
            )->group(
                'main_table.' . $columnName
            );
        }
        parent::_renderFiltersBefore();
    }

\app\code\vendor\module\Model\ResourceModel\Blog\Collection.php

protected function _afterLoad()  {
    $this->performAfterLoadBlog('vendor_module_store', 'blog_id');
    $this->_previewFlag = false;

    return parent::_afterLoad();
}

protected function _renderFiltersBefore() {
    $this->joinStoreRelationTable('vendor_module_store', 'blog_id');
}

So my question is, how do I go from here so the store_id column can be rendered with the correct store views?

Best Answer

Finally I have solved this issue. It turned out I was had two collections available for my grid and the one that was loaded did not contain the store_id index. For more information about the double collections see: Magento 2: Why does a UI Listing Component need Two Collections?

To solve this I have edited the Dependency Injection configuration at /app/code/vendor/module/etc/di.xml

Here I replaced this:

<virtualType name="Vendor\Module\Model\ResourceModel\Blog\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
<arguments>
    <argument name="mainTable" xsi:type="string">vendor_module_blog</argument>
    <argument name="resourceModel" xsi:type="string">Vendor\Module\Model\ResourceModel\Blog</argument>
</arguments>

with this:

<type name="Vendor\Module\Model\ResourceModel\Blog\Grid\Collection">
<arguments>
    <argument name="mainTable" xsi:type="string">vendor_module_blog</argument>
    <argument name="eventPrefix" xsi:type="string">module_blog_grid_collection</argument>
    <argument name="eventObject" xsi:type="string">module_grid_collection</argument>
    <argument name="resourceModel" xsi:type="string">Vendor\Module\Model\ResourceModel\Blog</argument>
</arguments>

This makes sure my collection from app\code\vendor\module\Model\ResourceModel\AbstractCollection.php is used for the grid and now the store_id with the store view works.

Related Topic