Back to Top

Magento 2 Development 23: Add Button

Updated 8 March 2024

We have seen various ways to edit the blog, in a few of the previous blogs. But we have still to see how can we add new blogs from the admin end.

Magento shows the Add New buttons just above the grid. So we will also display the “Add New Blog” button on the blog listing page.

For that, we have to edit the ui component file for the grid because Magento allows us to add buttons above the grid from the ui component file itself. So we have to edit the view/adminhtml/ui_component/blogmanager_blog_listing.xml

Updated code for view/adminhtml/ui_component/blogmanager_blog_listing.xml file

<?xml version="1.0" encoding="UTF-8"?>
<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">blogmanager_blog_listing.blogmanager_blog_listing_data_source</item>
            <item name="deps" xsi:type="string">blogmanager_blog_listing.blogmanager_blog_listing_data_source</item>
        </item>
        <item name="spinner" xsi:type="string">blogmanager_blog_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 Blog</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="blogmanager_blog_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">blogmanager_blog_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">entity_id</argument>
            <argument name="requestFieldName" xsi:type="string">entity_id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                <item name="update_url" xsi:type="url" path="mui/index/render"/>
                <item name="storageConfig" xsi:type="array">
                    <item name="indexField" xsi:type="string">entity_id</item>
                </item>
                </item>
            </argument>
        </argument>
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
            </item>
        </argument>
    </dataSource>
    <listingToolbar name="listing_top">
        <massaction name="listing_massaction" component="Magento_Ui/js/grid/tree-massactions">
            <argument name="data" xsi:type="array">
                <item name="data" xsi:type="array">
                <item name="selectProvider" xsi:type="string">blogmanager_blog_listing.blogmanager_blog_listing.blogmanager_blog_columns.ids</item>
                <item name="displayArea" xsi:type="string">bottom</item>
                <item name="indexField" xsi:type="string">entity_id</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="blog/manage/massDelete"/>
                    <item name="confirm" xsi:type="array">
                        <item name="title" xsi:type="string" translate="true">Delete Blogs?</item>
                        <item name="message" xsi:type="string" translate="true">Are you sure you want to delete the selected blogs?</item>
                    </item>
                </item>
                </argument>
            </action>
            <action name="status">
                <settings>
                    <type>status</type>
                    <label translate="true">Change status</label>
                    <actions>
                        <action name="0">
                            <type>enable</type>
                            <label translate="true">Enable</label>
                            <url path="blog/manage/massStatus">
                                <param name="status">1</param>
                            </url>
                        </action>
                        <action name="1">
                            <type>disable</type>
                            <label translate="true">Disable</label>
                            <url path="blog/manage/massStatus">
                                <param name="status">0</param>
                            </url>
                        </action>
                    </actions>
                </settings>
            </action>
        </massaction>
        <bookmark name="bookmarks"/>
        <columnsControls name="columns_controls"/>
        <filters name="listing_filters">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="templates" xsi:type="array">
                            <item name="filters" xsi:type="array">
                                <item name="select" xsi:type="array">
                                    <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item>
                                    <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
        </filters>
        <paging name="listing_paging"/>
    </listingToolbar>
    <columns name="blogmanager_blog_columns">
        <selectionsColumn name="ids">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="indexField" xsi:type="string">entity_id</item>
                </item>
            </argument>
        </selectionsColumn>
        <column name="entity_id">
            <settings>
                <filter>textRange</filter>
                <label translate="true">ID</label>
                <resizeDefaultWidth>25</resizeDefaultWidth>
            </settings>
        </column>
        <column name="user_name">
            <settings>
                <filter>text</filter>
                <label translate="true">User</label>
            </settings>
        </column>
        <column name="title">
            <settings>
                <filter>text</filter>
                <label translate="true">Title</label>
            </settings>
        </column>
        <column name="content" class="Webkul\BlogManager\Ui\Component\Listing\Columns\Content">
            <settings>
                <filter>false</filter>
                <sortable>false</sortable>
                <label translate="true">Content</label>
            </settings>
        </column>
        <column name="status" component="Magento_Ui/js/grid/columns/select">
            <settings>
                <options class="Webkul\BlogManager\Model\Blog\Status"/>
                <dataType>select</dataType>
                <filter>select</filter>
                <sortable>false</sortable>
                <label translate="true">Status</label>
            </settings>
        </column>
        <column name="updated_at" component="Magento_Ui/js/grid/columns/date">
            <settings>
                <filter>dateRange</filter>
                <dataType>date</dataType>
                <label translate="true">Updated</label>
            </settings>
        </column>
        <column name="created_at" component="Magento_Ui/js/grid/columns/date">
            <settings>
                <filter>dateRange</filter>
                <dataType>date</dataType>
                <label translate="true">Created</label>
            </settings>
        </column>
        <actionsColumn name="edit_action" class="Webkul\BlogManager\Ui\Component\Listing\Columns\EditAction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="indexField" xsi:type="string">entity_id</item>
                    <item name="viewUrlPath" xsi:type="string">blogmanager/manage/edit</item>
                    <item name="urlEntityParamName" xsi:type="string">id</item>
                    <item name="sortOrder" xsi:type="number">40</item>
                </item>
            </argument>
            <settings>
                <label translate="true">Edit</label>
            </settings>
        </actionsColumn>
        <actionsColumn name="delete_action" class="Webkul\BlogManager\Ui\Component\Listing\Columns\DeleteAction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="indexField" xsi:type="string">entity_id</item>
                    <item name="viewUrlPath" xsi:type="string">blogmanager/manage/delete</item>
                    <item name="urlEntityParamName" xsi:type="string">id</item>
                    <item name="sortOrder" xsi:type="number">50</item>
                </item>
            </argument>
            <settings>
                <label translate="true">Delete</label>
            </settings>
        </actionsColumn>
    </columns>
</listing>

Here as you can see we have added an item tag inside listing arguments to add the button. Similarly, you can add multiple buttons. And as you can see the code for the button is very self-explanatory.

Searching for an experienced
Magento 2 Company ?
Find out More

Now we need to create the controller action file for the new blog. Note that the URL for the new blog will be blog/manage/new which means the action class will be New. But new is a reserve word so we won’t be able to create a class with that name. However, Magento allows us to create NewAction (append Action after New) class for this kind of situation and it internally manages it. That means the action class file will be Controller/Adminhtml/Manage/NewAction.php

Code for Controller/Adminhtml/Manage/NewAction.php file

<?php
namespace Webkul\BlogManager\Controller\Adminhtml\Manage;

use Magento\Backend\App\Action;

class NewAction extends Action
{
    /**
     * Provides content
     *
     * @return void
     */
    public function execute()
    {
        $this->_forward('edit');
    }

    /**
     * Check Autherization
     *
     * @return boolean
     */
    public function _isAllowed()
    {
        return $this->_authorization->isAllowed('Webkul_BlogManager::add');
    }
}

The only thing to note here is $this->_forward(‘edit’); line. It forwards the current request to the edit action which means to the edit page. Note that it does not redirect but loads the edit page on the current URL (that is the new page URL). So it will show the edit page’s structure but form fields will be blank as shown below.

2021-07-21_13-12


But you won’t be able to create a new blog yet. For that, we have edit the save controller i.e. Controller/Adminhtml/Manage/Save.php

Updated code for Controller/Adminhtml/Manage/Save.php file

<?php
namespace Webkul\BlogManager\Controller\Adminhtml\Manage;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;

class Save extends Action
{
    /**
     * @var \Webkul\BlogManager\Model\BlogFactory
     */
    protected $blogFactory;

    /**
     * Dependency Initilization
     *
     * @param Context $context
     * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
     */
    public function __construct(
        Context $context,
        \Webkul\BlogManager\Model\BlogFactory $blogFactory
    ) {
        $this->blogFactory = $blogFactory;
        parent::__construct($context);
    }

    /**
     * Provides content
     *
     * @return Magento\Framework\Controller\Result\Redirect
     */
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        $data = $this->getRequest()->getParams();
        if (isset($data['entity_id']) && $data['entity_id']) {
            $model = $this->blogFactory->create()->load($data['entity_id']);
            $model->setTitle($data['title'])
                ->setContent($data['content'])
                ->setStatus($data['status'])
                ->save();
            $this->messageManager->addSuccess(__('You have updated the blog successfully.'));
        } else {
            $model = $this->blogFactory->create();
            $model->setTitle($data['title'])
                ->setContent($data['content'])
                ->setStatus($data['status'])
                ->save();
            $this->messageManager->addSuccess(__('You have successfully created the blog.'));
        }  
        return $resultRedirect->setPath('*/*/');
    }

    /**
     * Check Autherization
     *
     * @return boolean
     */
    public function _isAllowed()
    {
        return $this->_authorization->isAllowed('Webkul_BlogManager::save');
    }
}

Here we have added the else section to create a new blog entry in the table.

Now you can add the new blogs as shown below,

Vxb0s1A

As you can see here for the User column we have a blank cell. It is because we are performing left join with the customer table to get the data based on id.

We can create a class for that column, or we can edit the collection class of the grid to show “Admin” instead of empty. If you recall the grid collection class is Model/ResourceModel/Blog/Grid/Collection.php

Updated code for Model/ResourceModel/Blog/Grid/Collection.php file

<?php
namespace Webkul\BlogManager\Model\ResourceModel\Blog\Grid;

use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Search\AggregationInterface;
use Webkul\BlogManager\Model\ResourceModel\Blog\Collection as BlogCollection;
use Magento\Framework\Data\Collection\EntityFactoryInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Collection extends BlogCollection implements SearchResultInterface
{
    /**
     * Dependency Initilization
     *
     * @param EntityFactoryInterface $entityFactory
     * @param LoggerInterface $logger
     * @param FetchStrategyInterface $fetchStrategy
     * @param ManagerInterface $eventManager
     * @param [type] $mainTable
     * @param [type] $resourceModel
     * @param [type] $model
     * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
     * @param AbstractDb|null $resource
     */
    public function __construct(
        EntityFactoryInterface $entityFactory,
        LoggerInterface $logger,
        FetchStrategyInterface $fetchStrategy,
        ManagerInterface $eventManager,
        $mainTable,
        $resourceModel,
        $model = \Magento\Framework\View\Element\UiComponent\DataProvider\Document::class,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
        AbstractDb $resource = null
    ) {
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $connection,
            $resource
        );
        $this->_init($model, $resourceModel);
        $this->setMainTable($mainTable);
    }

    /**
     * Get Agrigations
     *
     * @return \Magento\Framework\Api\Search\AggregationInterface
     */
    public function getAggregations()
    {
        return $this->aggregations;
    }

    /**
     * Set Agrigations
     *
     * @param \Magento\Framework\Api\Search\AggregationInterface $aggregations $aggregations
     * @return \Magento\Framework\Api\Search\SearchResultInterface
     */
    public function setAggregations($aggregations)
    {
        $this->aggregations = $aggregations;
    }

    /**
     * Get Search Criteria
     *
     * @return null
     */
    public function getSearchCriteria()
    {
        return null;
    }
    
    /**
     * Set Search Criteria
     *
     * @param \Magento\Framework\Api\SearchCriteriaInterface|null $searchCriteria
     * @return this
     */
    public function setSearchCriteria(
        \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null
    ) {
        return $this;
    }

    /**
     * Returns the total count of the bolg
     *
     * @return int
     */
    public function getTotalCount()
    {
        return $this->getSize();
    }

    /**
     * Sets the total count of the bolg
     *
     * @param int $totalCount
     * @return this
     */
    public function setTotalCount($totalCount)
    {
        return $this;
    }

    /**
     * Set Item
     *
     * @param array|null $items
     * @return int
     */
    public function setItems(array $items = null)
    {
        return $this;
    }

    /**
     * Render Filter before
     *
     * @return void
     */
    protected function _renderFiltersBefore()
    {
        $cgfTable = $this->getTable('customer_grid_flat');
        $this->getSelect()->joinLeft(
            $cgfTable.' as cgf',
            'main_table.user_id = cgf.entity_id',
            []
        )
        ->columns('IFNULL(cgf.name, "Admin") AS user_name');

        parent::_renderFiltersBefore();
    }
    
    /**
     * Initilize Select
     *
     * @return void
     */
    protected function _initSelect()
    {
        $this->addFilterToMap('user_name', 'cgf.name');
        parent::_initSelect();
    }
}

->columns(‘IFNULL(cgf.name, “Admin”) AS user_name’) This is the line that we have to focus on. The columns will create the pseudo column. The actual SQL query that we get at the end is shown below,

2021-07-21_16-27

Note that the filters will not work for the text “Admin” for the User column. We have to do some complex changes if we want the filter to work too. Which we will be ignoring for now.

Now the grid should look fine,

2021-07-21_16-34


Next Blog -> Magento 2 Development 24: Loading Magento’s Data

Previous Blog -> Magento 2 Development 22: Multi tab form

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home