AJAX Flash messages

I’m using flash messages, much like as show here: http://www.yiiframework.com/doc/cookbook/21/

Is there a way to use flash messages during AJAX? It seems that it would be very useful to submit data to a controller with ajax, and have a flash message triggered for the response.

Why not? AJAX-request is just another request. So you can get/set flashes as you did before.

So the only way to do this would be to set the flash in the controller, and then echo or renderPartial a view with the Yii::app()->user->getFlash(…)?

Yes. You can either render it with next page load or do polling requests to controller with ajax until it returns a message. Internally it’s the same things. What’s different is clientside part.

So how do we actually do this?

I added:


Yii::app()->user->setFlash('success', "The user has been deleted successfully.");

in my actionDelete() but it doesn’t work for AJAX requests. What else do I need to do?

I expect that the problem you’re having with using the default Gii CRUD actionDelete is that when your action succeeds your AJAX call is sent a redirect when what you actually need is the content of the message… Well, I’ve never seen any AJAX system to handle a redirect the same way a browser might, loading the URL the user is redirected to, and jQuery’s implementation is no exception to this.

My suggestion would be to, as redirects are useless on an AJAX call anyway, modify your actionDelete as follows:


if(Yii::app()->request->getIsAjaxRequest()) {

    echo Yii::app()->user->getFlash(...);

} else {

    $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array(...));

}

At-least this way your user’s browser is sent the message. You’ll need to make a couple more changes to ensure it’s shown, however.

Firstly, in the code that performs your AJAX call, run the following function:




gotFlash(message)

{

    $('#Flash').html(message).fadeIn().animate({opacity: 1.0}, 3000).fadeOut("slow");

}



Now, this sets the content of the element with ID ‘success’, and animates it in and out, but it doesn’t do anything unless there’s an element with that ID on the page already… It’s notable that the code in the cookbook only places its element with class ‘info’ if there was a flash message when the page was loaded. I’d thus suggest altering their code as follows.


    <?php $HasFlash = Yii::app()->user->hasFlash('Flash'); ?>

    <div class="info" id='Flash' <?php if(!$HasFlash) echo "style='display: none'"?>>

        <?php if($HasFlash) echo Yii::app()->user->getFlash('Flash'); ?>

    </div>

Now you should see your flash appearing as you want it… Note that I switched to using an ID rather than a class. Otherwise, if you had several info boxes, you’d end-up setting the contents of all of them with the $(’.info’).html() code. IDs should be unique.

Another, more complex, way to do it would be to check if the desired div existed and to use jQuery’s .append() function to create the div if it weren’t there… I think the above works fine, however.