Magento 2 – How to Add Popup on Custom Button in Order View Page and Pass Information to Controller

controllersjavascriptmagento-2.1magento2plugin

I have added a custom button on the Sales Order View page in Admin using Plugin.

When that button clicks it should open a popup with form and when I submit that form then this information should pass to the controller to process that data and again redirect the same order page.

I have added a button using the below plugin. Please help me out to achieve the above requirement.

Plugin File /var/www/magento/app/code/MyCompany/Customadmin/Plugin/CreateWarrantyOrder.php

<?php

namespace MyCompany\Customadmin\Plugin;

/**
 * Class View
 *
 * @package MyCompany\Customadmin\Plugin\CreateWarrantyOrder
 */
class CreateWarrantyOrder
{

    public function beforeSetLayout(
        \Magento\Sales\Block\Adminhtml\Order\View $subject,
        $layout
    ) {
        $subject->addButton(
            'sendordersms',
            [
                'label' => __('Create Warranty Order'),
                'onclick' => "",
                'class' => 'action-default action-warranty-order',
            ]
        );
        return [$layout];
    }

    public function afterToHtml(
        \Magento\Sales\Block\Adminhtml\Order\View $subject,
        $result
    ) {
        if($subject->getNameInLayout() == 'sales_order_edit'){
            $customBlockHtml = $subject->getLayout()->createBlock(
                \MyCompany\Customadmin\Block\Adminhtml\Order\ModalBox::class,
                $subject->getNameInLayout().'_modal_box'
            )->setTemplate('MyCompany_Customadmin::order/modalbox.phtml')
                ->toHtml();

            return $result.$customBlockHtml;
        }
        return $result;
    }
}

Modalbox – /var/www/magento/app/code/MyCompany/Customadmin/view/adminhtml/templates/order/modalbox.phtml

<?php
/**
 * @var $block \MyCompany\Customadmin\Block\Adminhtml\Order\ModalBox
 */
echo $block->getInfo();
$controllerUrl = $block->getUrl("customadmin/adminhtml/order");
?>
<div id="popup-modal" style="display: none">

    <form action="<?php echo $controllerUrl; ?>" method="POST">
        <input name="firstname" type="text">
        <input name="lastname" type="text">
        <input name="phone" type="text">
        <input type="submit" value="Submit">
        <input type="reset" value="Clear">
    </form>
</div>

<script>
    require(
        [
            'jquery',
            'Magento_Ui/js/modal/modal'
        ],
        function (
            $,
            modal
        ) {
            var options = {
                type: 'popup',
                responsive: true,
                innerScroll: true,
                title: 'Create Order Warranty',
                modalClass: 'custom-modal',
                buttons: [{
                    text: $.mage.__('Close'),
                    class: '',
                    click: function () {
                        this.closeModal();
                     }
                }]
            };

            var popup = modal(options, $('#popup-modal'));
            $("#sendordersms").click(function() {
                $("#popup-modal").modal('openModal');
            });
        }

    );
</script>

Block File
/var/www/magento/app/code/MyCompany/Customadmin/Block/Adminhtml/Order/ModalBox.php

<?php

namespace MyCompany\Customadmin\Block\Adminhtml\Order;

/**
 * Class ModalBox
 *
 * @package MyCompany\Customadmin\Block\Adminhtml\Order
 */
class ModalBox extends \Magento\Backend\Block\Template
{

    /**
     * Constructor
     *
     * @param \Magento\Backend\Block\Template\Context  $context
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * @return string
     */
    public function getInfo()
    {
        $firstname = $this->getRequest()->getParam('firstname');

        \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class)->debug('ModalBox data >>> ' . $firstname);

        return __('Hello Developer! This how to get the ');
    }
}

Controller File – /var/www/magento/app/code/MyCompany/Customadmin/Controller/Adminhtml/Order/OrderController.php

<?php
namespace MyCompany\Customadmin\Controller\Adminhtml\Order;

class OrderController extends \Magento\Backend\App\Action
{
    /**
     * Hello test controller page.
     *
     * @return \Magento\Backend\Model\View\Result\Page
     */
    /**
     * Check Permission.
     *
     * @return bool
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('MyCompany_Customadmin::ordercontroller');
    }


    public function execute()
    {
        if ($order = $this->_initOrder()) {
            try {

                 $firstname = $this->getRequest()->getParam('firstname');

                \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class)->debug('OrderController data >>> ' . $firstname);


                /*$connection = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection')->getConnection();
                $sql = "UPDATE sales_order SET order_file_sent = '0' WHERE entity_id = '".$order->getEntityId()."'" ; 
                $connection->query($sql) ;*/



            } catch (\Exception $e) {

                $this->messageManager->addError(__('Failed '));
                $this->logger->critical($e);

            }

            $this->messageManager->addSuccess(__('Success'));
            return $this->resultRedirectFactory->create()->setPath(
                'sales/order/view',
                [
                    'order_id' => $order->getEntityId()
                ]
            );
        }

        return $this->resultRedirectFactory->create()->setPath('sales/*/');
    }

}

Routes.xml
/var/www/magento/app/code/MyCompany/Customadmin/etc/adminhtml/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="admin">
        <route id="customadmin" frontName="customadmin">
            <module name="MyCompany_Customadmin"/>
        </route>
    </router>
</config>

di.xml
/var/www/magento/app/code/MyCompany/Customadmin/etc/adminhtml/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Block\Adminhtml\Order\View">
        <plugin name="CreateWarrantyOrder" type="MyCompany\Customadmin\Plugin\CreateWarrantyOrder"/>
    </type>
</config>

Best Answer

If you want to call a pop on your custom button click then you have to create a modal box .

  • For create a modal box, you need to create a child block of Magento\Sales\Block\Adminhtml\Order\View .
  • On that child build a modal box with form
  • After that add this child Block HTML out with Magento\Sales\Block\Adminhtml\Order\View out using toHtml()plugin. after Plugi afterToHtml().

Create a Block class and a phtml to render the popup and form

Block Class: app\code\MyCompany\Customadmin\Block\Adminhtml\Order\ModalBox and code Will be like:

   <?php


namespace StackExchange\MagentoTest\Block\Adminhtml\Order;

/**
 * Class ModalBox
 *
 * @package StackExchange\MagentoTest\Block\Adminhtml\Order
 */
class ModalBox extends \Magento\Backend\Block\Template
{

    /**
     * Constructor
     *
     * @param \Magento\Backend\Block\Template\Context  $context
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * @return string
     */
    public function getInfo()
    {
        //Your block cod
        return __('Hello Developer! This how to get the ');
    }
    public function getFormUrl()
    {
        $orderId = false;
        if($this->hasData('order')){
            $orderId = $this->getOrder()->getId();
        }
        return $this->getUrl('magentotest/order/order',[
            'order_id' => $orderId
        ]);
    }
}
Phtml code is below and the location is:

Location: app/code/MyCompany/Customadmin/view/adminhtml/templates/order/modalbox.phtml

Code

   <?php
/**
 * @var $block \StackExchange\MagentoTest\Block\Adminhtml\Order\ModalBox
 */

?>
<div id="popup-modal" style="display: none">

    <form action="<?= $block->escapeUrl($block->getFormUrl())?>" method="post"
          id="order-view-add-warranty-form">
        <input name="firstname" type="text">
        <input name="lastname" type="text">
        <input name="phone" type="text">
        <input name="bookingTime" type="date">

        <input type="button" value="Submit" id="order-view-add-warranty">
    </form>
</div>

<script>
    require(
        [
            'jquery',
            'Magento_Ui/js/modal/modal'
        ],
        function (
            $,
            modal
        ) {
            var options = {
                type: 'popup',
                responsive: true,
                innerScroll: true,
                title: 'Modal Title',
                modalClass: 'custom-modal',
                buttons: [{
                    text: $.mage.__('Close'),
                    class: '',
                    click: function () {
                        this.closeModal();
                     }
                }]
            };

            var popup = modal(options, $('#popup-modal'));
            $("#sendordersms").click(function() {
                $("#popup-modal").modal('openModal');
            });

            $('#order-view-add-warranty').click(function () {
                $('#order-view-add-warranty-form').append($('<input>', {
                    'name': 'form_key',
                    'value': window.FORM_KEY,
                    'type': 'hidden'
                }));
                $('#order-view-add-warranty-form').submit();

            });

        }

    );
</script>

Update a plugin class MyCompany\Customadmin\Plugin\CreateWarrantyOrder

Add new after plugin on toHtml() on this class and append MyCompany\Customadmin\Block\Adminhtml\Order\ModalBox block output using this after plugin afterToHtml. And code:

<?php


namespace StackExchange\MagentoTest\Plugin\Magento\Sales\Block\Adminhtml\Order;

/**
 * Class View
 *
 * @package StackExchange\MagentoTest\Plugin\Magento\Sales\Block\Adminhtml\Order
 */
class View
{

    public function beforeSetLayout(
        \Magento\Sales\Block\Adminhtml\Order\View $subject,
        $layout
    ) {
        $subject->addButton(
            'sendordersms',
            [
                'label' => __('Create Warranty Order'),
                'onclick' => "",
                'class' => 'action-default action-warranty-order',
            ]
        );
        return [$layout];
    }

    public function afterToHtml(
        \Magento\Sales\Block\Adminhtml\Order\View $subject,
        $result
    ) {
        if($subject->getNameInLayout() == 'sales_order_edit'){
            $customBlockHtml = $subject->getLayout()->createBlock(
                \StackExchange\MagentoTest\Block\Adminhtml\Order\ModalBox::class,
                $subject->getNameInLayout().'_modal_box'
            )->setOrder($subject->getOrder())
                ->setTemplate('StackExchange_MagentoTest::order/modalbox.phtml')
                ->toHtml();
            return $result.$customBlockHtml;
        }
        return $result;
    }
}

Changs at Controller code

   <?php

namespace StackExchange\MagentoTest\Controller\Adminhtml\Order;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
use Magento\Sales\Controller\Adminhtml\Order as AdminOrder;

class Order extends AdminOrder implements HttpPostActionInterface
{
    /**
     * Changes ACL Resource Id
     */
    const ADMIN_RESOURCE = 'Magento_Sales::hold';
    /**
     * @inheritDoc
     */
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();

        $order = $this->_initOrder();
        if ($order) {
            $post = $this->getRequest()->getPostValue();

            echo "<pre>";
            print_r($post);
            exit;
            $resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]);
            return $resultRedirect;
        }
        $resultRedirect->setPath('sales/*/');
        return $resultRedirect;
    }
}

Above code are working on local. You have to changes class name and URL as per your requirement.

MOdule share at https://github.com/devamitbera/magento-stackexchange/blob/master/StackExchange-306851.zip

Related Topic