Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the Magento built-in messages system in custom controller+action

I am ajaxifying my magento store, and pretty much everything is going swimmingly, except for one thing:

Problem: I seem to be unable to retrieve and display the messages block in the responses to AJAX requests.

Explanation: I am talking about the red (or green, when it is a success message) bar that appears to the user after trying something that didn't work (e.g. adding more items to the cart than the stock allows). When responding to certain ajax requests that generate errors, I want to display the messages' mark up through a pretty much empty template, which is used to render the response for this ajax request. When no error occurs, a different appropriate response is rendered.

Things I've tried: Here's a few lines of PHP code which I've tried to use:

$_messages = Mage::getSingleton("core/session")->getMessages();
echo $this->getLayout()->createBlock("core/messages")->setMessages($_messages)->getGroupedHtml();

echo $this->getMessagesBlock()->getGroupedHtml();

echo Mage::app()->getLayout()->getMessagesBlock()->
        setMessages(Mage::getSingleton('customer/session')->getMessages(true))->getGroupedHtml();

Mage::logging the data shows empty message collections.

Here is the layout XML (I'm using $this->loadLayout('ajax_msg_handle'); from the controller):.

<ajax_msg_handle>
  <block type="core/template" name="error.root" output="toHtml" template="page/html/ajax-messages.phtml">
    <block type="core/messages" name="global_messages" as="global_messages"/>
    <block type="core/messages" name="messages" as="messages"/>
  </block>
</ajax_msg_handle>

Also a point of detail, I've considered the following:

Most actions, like the cart's "delete", "edit" and the product page's "add to cart", first redirect to a different place, so a second request is made, which shows the error. Maybe these messages are never displayed right away, but only when responding to the request after the one generating the error. So I've tried to follow this possible convention by redirecting to an action that displays these messages, but this didn't work either.

If anyone can tell me how to get those messages to appear, it'll make my day.

like image 679
pancake Avatar asked Oct 09 '22 09:10

pancake


1 Answers

the messages block you're trying to use is not suppose to work for AJAX queries. As you've pointed out, it only appears after a redirect, ie:

  • the message is set in the session through something like: Mage::getSingleton('adminhtml/session')->addError(Mage::helper('modulename')->__('error message'));
  • then is the redirect: $this->_redirect('*/*/');
  • which triggers a brand new query, which loads the layout. As the layout is set up, as there is a message, it shows up.

In order to show this message block directly in the AJAX call (ie, without redirect), you have to:

  • in your controller's action: set the message and load the block:

    Mage::register('message', Mage::helper('yourmodule')->__('the error message');
    $layout = $this->getLayout();
    $update = $layout->getUpdate();
    $update->load('ajax_msg_handle'); //loading your custom handle, defined in your module's layout .xml file
    $layout->generateXml();
    $layout->generateBlocks();
    $output = $layout->getOutput();
    $this->getResponse()->setBody(Mage::helper('core')->jsonEncode(array('error' => $output)));
    
  • in your .phtml echo the message:

    <ul class="messages">
        <li class="error-msg">
            <ul>
                <li><?php echo Mage::registry('message'); ?></li>
            </ul>
        </li>
    </ul>
    
  • output the response in your javascript code in the onComplete part of your ajax call:

    onComplete: function(transport) {
        $$('.main-col-inner')[0].insert({before:transport.responseText.evalJSON().error});
        Element.hide('loading-mask');
    }
    

Note that it would better practise to make your own block type, that would extend Mage_Core_Block_Messages and manage the message in that block's methods, instead of using the registry.
Hope That Helps

like image 159
OSdave Avatar answered Oct 13 '22 10:10

OSdave