Magento 2: Create Widget Programmatically & Assign Static Block to it

This article shows how you can add/create Widget using Upgrade Script of a module in Magento 2.

This code is useful when you need to auto add/create widget while upgrading your custom module.

Here, we will also create a CMS Static Block and assign that newly created static block to the Widget.

Add Widget and Static Block via UpgradeData Setup Script

– At first, this will add cms static block when you upgrade your custom module.
– Then the widget will be created.
– The newly created static block will be assigned to that widget.
– The widget position is set as sidebar.additional. So, the widget content is displayed in the sidebar in frontend.

Here, I am using my custom module named Chapagain_HelloWorld.

In the below code, you can see that I have checked for my module’s version 0.1.1. So, while upgrading the module to version 0.1.1, the below UpgradeData script will get executed.

File: app/code/Chapagain/HelloWorld/Setup/UpgradeData.php

<?php

namespace Chapagain\HelloWorld\Setup;

use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class UpgradeData implements \Magento\Framework\Setup\UpgradeDataInterface
{
    /**
     * @var \Magento\Cms\Model\BlockFactory
     */
    private $blockFactory;

    /**
     * @var \Magento\Widget\Model\Widget\InstanceFactory
     */
    private $widgetFactory;

    /**
     * @var \Magento\Framework\App\State
     */
    private $state;

    /**
     * UpgradeData constructor
     * 
     * @param \Magento\Cms\Model\BlockFactory $blockFactory
     * @param \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory
     */
    public function __construct(
        \Magento\Cms\Model\BlockFactory $blockFactory,
        \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory,
        \Magento\Framework\App\State $state
    )
    {
        $this->blockFactory = $blockFactory;
        $this->widgetFactory = $widgetFactory;
        $this->state = $state;
    }

    /**
     * Upgrade data for the module
     *
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     * @return void
     * @throws \Exception
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        // Set Area code to prevent the Exception during setup:upgrade 
        $this->state->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML);

        $setup->startSetup();
        if (version_compare($context->getVersion(), '0.1.1') < 0) {
            $cmsBlockData = [
                'title' => 'Test Block',
                'identifier' => 'test-block',
                'content' => "<div class='block'>
                                <div class='block-title'><strong role='heading' aria-level='2'>My test block</strong></div>
                                <div class='block-content'>
                                <div class='empty'>Learn more about the site.</div>
                                </div>
                                </div>",
                'is_active' => 1,
                'stores' => [0],
                'sort_order' => 0
            ];

            $cmsBlock = $this->blockFactory->create()->setData($cmsBlockData)->save();

            $widgetData = [
                'instance_type' => 'Magento\Cms\Block\Widget\Block',
                'instance_code' => 'cms_static_block',
                'theme_id' => 5,
                'title' => 'Test Widget',
                'store_ids' => '0',
                'widget_parameters' => '{"block_id":"'.$cmsBlock->getId().'"}',
                'sort_order' => 0,
                'page_groups' => [[
                    'page_id' => 1,
                    'page_group' => 'all_pages',
                    'layout_handle' => 'default',
                    'for' => 'all',
                    'all_pages' => [
                        'page_id' => null,
                        'layout_handle' => 'default',
                        'block' => 'sidebar.additional',
                        'for' => 'all',
                        'template' => 'widget/static_block/default.phtml'
                    ]
                ]]
            ];    

            $this->widgetFactory->create()->setData($widgetData)->save();    
        }
        $setup->endSetup();
    }
}
`

Hope this helps. Thanks.