Magento – show error message through plugin Magento2

-setupmagento2pluginresponse

Hi i have use a plugin feature in my module to check the zipcode is available in the module or not .Which works fine but on validating i have set the error message like

<?php

namespace Company\Mymodule\Plugin\Checkout\Model;
use Magento\Framework\Exception\NoSuchEntityException;

class ShippingInformationManagement
{

    protected $_messageManager;
    protected $jsonResultFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\Controller\Result\JsonFactory $jsonResultFactory,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
    ) {
        $this->_messageManager = $messageManager;
        $this->jsonResultFactory = $jsonResultFactory;
    }

    public function beforeSaveAddressInformation(
        \Magento\Checkout\Model\ShippingInformationManagement $subject,
        $cartId,
        \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation

    )
    {
    $address = $addressInformation->getShippingAddress();
    $postcode = $address->getData('postcode');
    $objectManager =   \Magento\Framework\App\ObjectManager::getInstance();
    $connection = $objectManager->get('Magento\Framework\App\ResourceConnection')->getConnection('\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION'); 
    $result1 = $connection->fetchAll("SELECT shipregioncodes FROM shipregioncodes_shipregioncodes WHERE shipregioncodes=$postcode");
    $count = count($result1);
    $result = $this->jsonResultFactory->create();
    if($count==0){
            $this->_messageManager->addError("hiiiiiiii");
            throw new NoSuchEntityException(
                __('Shipping is not available on provided zipcode %1', $postcode)
            );

    }
}
}

di.xml code is below

<type name="Magento\Checkout\Model\ShippingInformationManagement">
    <plugin name="get_shipping_info" type="Company\Mymodule\Plugin\Checkout\Model\ShippingInformationManagement" sortOrder="1"/>
</type>

it only shows the message in the console not on the site.Please suggest me how can i fix this.
thanks

Best Answer

If it's checkout and it is displayed in console it's possible that is ajax. Maybe try to send back html with text of messages in json an then display it using javascript file responsible for this section of page. Search in core controllers for example of json response cooperating with message manager.

EDIT

Here you have my controller class for custom newsletter ajax module:

use \Magento\Customer\Api\AccountManagementInterface as CustomerAccountManagement;
use \Magento\Customer\Model\Session;
use \Magento\Customer\Model\Url as CustomerUrl;
use \Magento\Framework\App\Action\Context;
use \Magento\Framework\Controller\Result\JsonFactory;
use \Magento\Framework\View\LayoutFactory;
use \Magento\Newsletter\Controller\Subscriber\NewAction;
use \Magento\Newsletter\Model\SubscriberFactory;
use \Magento\Store\Model\StoreManagerInterface;

class NewAjax extends NewAction
{

/**
 * @var \Magento\Framework\Controller\Result\JsonFactory
 */
protected $resultJsonFactory;

/**
 * @var \Magento\Framework\View\LayoutFactory
 */
protected $layoutFactory;


/**
 * Di.
 * 
 * @param \Magento\Customer\Api\AccountManagementInterface $customerAccountManagement
 * @param \Magento\Customer\Model\Session $customerSession
 * @param \Magento\Customer\Model\Url $customerUrl
 * @param \Magento\Framework\App\Action\Context $context
 * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
 * @param \Magento\Framework\View\LayoutFactory $layoutFactory
 * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
 * @param \Magento\Store\Model\StoreManagerInterface $storeManager
 */
public function __construct(
    CustomerAccountManagement $customerAccountManagement,
    Session $customerSession,
    CustomerUrl $customerUrl,
    Context $context,
    JsonFactory $resultJsonFactory,
    LayoutFactory $layoutFactory,
    SubscriberFactory $subscriberFactory, 
    StoreManagerInterface $storeManager
)
{
    parent::__construct($context, $subscriberFactory, $customerSession, 
                        $storeManager, $customerUrl, $customerAccountManagement);

    $this->resultJsonFactory = $resultJsonFactory;
    $this->layoutFactory = $layoutFactory;
}


/**
 * Ajax way of adding subscription. Uses parent action for validation + response with '<div>' containing error/success 
 * messages.
 * 
 * @return \Magento\Framework\Controller\Result\Json
 */
public function execute()
{
   if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
        $email = (string)$this->getRequest()->getPost('email');

        $block = $this->layoutFactory->create()->getMessagesBlock();
        $error = false;

        try {
            $this->validateEmailFormat($email);
            $this->validateGuestSubscription();
            $this->validateEmailAvailable($email);

            $status = $this->_subscriberFactory->create()->subscribe($email);
            if ($status == \Magento\Newsletter\Model\Subscriber::STATUS_NOT_ACTIVE) {
                $this->messageManager->addSuccessMessage(__('The confirmation request has been sent.'));
            } else {
                $this->messageManager->addSuccessMessage(__('Thank you for your subscription.'));
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $error = true;
            $this->messageManager->addExceptionMessage(
                $e,
                __('There was a problem with the subscription: %1', $e->getMessage())
            );
        } catch (\Exception $e) {
            $error = true;
            $this->messageManager->addExceptionMessage($e, __('Something went wrong with the subscription.'));
        }
    }

    $block->setMessages($this->messageManager->getMessages(true));
    $resultJson = $this->resultJsonFactory->create();

    return $resultJson->setData([
        'messages' => $block->getGroupedHtml(),
        'error' => $error
    ]);
}

}

Key is here:

$block = $this->layoutFactory->create()->getMessagesBlock();
$error = false;

I get message block and prepare error flag. After that you can see that in case of any exception in catch blocks I change value of error flag. In the end I set messages from messageManager to my message block and add it to my json response:

$block->setMessages($this->messageManager->getMessages(true));
$resultJson = $this->resultJsonFactory->create();

    return $resultJson->setData([
        'messages' => $block->getGroupedHtml(),
        'error' => $error
    ]);

After that in my javascript, which gets response from controller I inject into DOM block with messages if flag is true - in block success:

function addSubscription(newAjaxUrl)
{
    $('body').on('click', '.newsletter-button', function() {
        var email = getSubscriptionEmail();
        if (validateEmail(email)) {
            $.ajax({
                showLoader: true,
                url: newAjaxUrl,
                type: 'post',
                data: {'email': email},
                dataType: 'json',
                success: function (result) {
                    clearMessage();
                    $(result.messages).insertAfter('.foot-mess');
                    clearEmailInput();
                    fadeOutEmail();
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    clearMessage();
                    console.error(textStatus + ' ' + jqXHR.status + ': ' + errorThrown);
                }
            });
        } else {
            clearMessage();
            $('.newsletter-ajax-input').addClass('newsletter-ajax-input mage-error');
            $(FRONTEND_VALIDATION_MESSAGE).insertAfter('.foot-mess');
        }
    });

Please note that it is done outside of checkout so it can give some directions and advices but you would not be able to adopt it completely. Although it show message manager can be used in ajax calls.