8

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?

  • Show your collection class code. – Sohel Rana Apr 16 '16 at 10:44
  • The module is very similar as the CMS pages module. I have copied a function from \app\code\vendor\module\Model\ResourceModel\AbstractCollection.php which I believe retrieves the collection for the grid including the store_id. I'm somewhat of a noob though so I might be wrong. – Solide Apr 17 '16 at 19:23
  • Collection can handle one table(by default). If you need to join another table then you need to work with '_afterLoad', '_renderFiltersBefore' and finally add a map. – Sohel Rana Apr 18 '16 at 6:00
  • Ok, I already got the _afterload and _renderFiltersBefore (I have edited the question). Not sure if I have added a map already, could you clarify this? Thank you in advance. – Solide Apr 18 '16 at 19:24
  • @Solide have you resolved that issue? – Prashant Valanda May 12 '16 at 6:52
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.