26

I have a Module which processes a Post action, and then redirects.

Now there are error cases, and I would like to show messages for them to the users.

I already know, that this code adds the message to the session.

$this->messageManager->addError(
   $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($message)
);

But I dont see how to trigger the rendering.

Currently it is only shown when i execute another action, which already uses this in a working way.

Like for example the login with wrong password.

3

5 Answers 5

13

Not sure if this is what you are looking for, but I'm giving it a shot.
You can retrieve the messages like this:

$messages = $this->messageManager->getMessages(true);  

where messageManager is an instance of \Magento\Framework\Message\ManagerInterface.

In the core, this is used for ajax calls in order to return the error messages in the json response like this (\Magento\Catalog\Controller\Adminhtml\Category\Move):

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

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

For actions with output you shouldn't do anything (I think). The default.xml layout file from the Magento_Theme module already contains this block <block class="Magento\Framework\View\Element\Messages" name="messages" as="messages" template="Magento_Theme::messages.phtml"/> that should handle the messages.

[Side note]:
Don't use $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($message). Inject in your constructor an instance of Magento\Framework\Escaper and use that.

12
  • The loginPost action is also able to trigger this, and it does a redirect to the login page after this and shows it then. Thats the case I have, too. No ajax, no same page.
    – Flyingmana
    Sep 15, 2015 at 8:29
  • That's what I said...this should be handled by default. You should not need to make any changes. The session message should be displayed on the next page.
    – Marius
    Sep 15, 2015 at 8:35
  • 2
    And thats why I do this question. Because its not. I even redirect to the same page(login) so obviously there is an additional step needed. As I said, even on the login page my message is only shown after i tried the login which posts its own message
    – Flyingmana
    Sep 15, 2015 at 8:38
  • 1
    OK. I'll dig deeper. This looks strange to me.
    – Marius
    Sep 15, 2015 at 8:39
  • 2
    @Flyingmana. I found something. The session messages are retrieved after a call is made to /customer/section/load/. Maybe that helps.
    – Marius
    Sep 15, 2015 at 9:31
26

You need to use object injection method on ur module action class to inject the message manager object into it, i provided an example of what u can do. Hope it helps

class Example
{
    protected $_messageManager;

    public function __construct(
        \Magento\Framework\Message\ManagerInterface $messageManager
    ) {
        $this->_messageManager = $messageManager;
    }

    public function method( ) {
        ..
        $message = '...';
        $this->_messageManager->addError($message);
        ..
    }
}
5
  • is there any getError function? i want to fetch the message Oct 25, 2018 at 7:08
  • 1
    the addError method is deprecated should be addErrorMessage now
    – jamil
    Nov 21, 2018 at 17:56
  • @jafarpinjar , nope. I would change it in translation , but if you cant change it in translation, you can get the error message by event observer and manipulate it there.
    – Karvin Ong
    Jun 7, 2019 at 1:45
  • @jamil , yes agreed. addError is depreciated but still supported on ver 2.3.1 :)
    – Karvin Ong
    Jun 7, 2019 at 1:47
  • use addErrorMessage instead.
    – Ferrmolina
    Nov 27, 2020 at 16:55
5

you can also find the message manager accessible through $context that is injected into actions constructors:

class yourAction extends \Magento\Framework\App\Action\Action
{
    /** var ... */
    protected $_messageManager;

    public function __construct(Context $context)
    {
        $this->_messageManager = $context->getMessageManager();
        parent::__construct($context);
    }

Next just use as mentioned in answers above

$this->_messageManager->addError($message);

Hope it helps

2

For me it looks like you need to add special block for your messages if you want to show them in non-JS way.

For example in Magento\Checkout\view\frontend\layout\checkout_cart_index.xml there is:

<referenceContainer name="page.messages">
    <block class="Magento\Checkout\Block\Cart\ValidationMessages" name="checkout.cart.validationmessages"/>
</referenceContainer>

Magento\Checkout\Block\Cart\ValidationMessages block extends core \Magento\Framework\View\Element\Messages block which is responsible for rendering messages.

Blocks defined in default.xml are for JS messages only I believe.

1
  • How do you add it to checkout_index_index.xml?
    – tread
    Apr 7, 2017 at 13:35
1

Take a look at

vendor/magento/module-customer/view/frontend/web/js/customer-data.js

/**
 * Events listener
 */
$(document).on('ajaxComplete', function (event, xhr, settings) {
    var sections,
        redirects;

    if (settings.type.match(/post|put/i)) {
        sections = sectionConfig.getAffectedSections(settings.url);

        if (sections) {
            customerData.invalidate(sections);
            redirects = ['redirect', 'backUrl'];

            if (_.isObject(xhr.responseJSON) && !_.isEmpty(_.pick(xhr.responseJSON, redirects))) {
                return;
            }
            customerData.reload(sections, true);
        }
    }
});

As we can see, there is a built-in checking function already. If our response contains keywords: 'redirect', 'backUrl', the message will load after redirecting.

  • After ajax complete, the customer will be invalidated. This will be "trigger" reloading message session.
  • Checking keywords: 'redirect', 'backUrl'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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