You are viewing revision #3 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
A flash message is used in order to keep a message in session and make sure it’s removed from session after it has been displayed to the user. Therefore flash messages are available only in the current and the next requests. Flash messages can be set using the setFlash() Method of [CWebUser]. For example if you would like to inform the user, that his changes were successfully saved, you could add the following line to your Controller:
Yii::app()->user->setFlash('success',"Data saved!");
In this example we used the key 'success'. If you want to define more than one flash messages, you will have to use different keys. To check for flash messages we use the hasFlash() Method and to obtain the flash message we use the getFlash() Method. So showing of the flash message in a view is done by
<?php if(Yii::app()->user->hasFlash('success')):?>
<div class="info">
<?php echo Yii::app()->user->getFlash('success'); ?>
</div>
<?php endif; ?>
These few lines of code will make a flash message with the key "success" visible to the user within a div of class "info". The message will be displayed until this or another page is (re)loaded in the browser.
If you want the flash message to appear somewhere above the content and then automatically fade out after a few seconds, you will have to add the following lines to your view:
<?php
Yii::app()->clientScript->registerScript(
'myHideEffect',
'$(".info").animate({opacity: 1.0}, 3000).fadeOut("slow");',
CClientScript::POS_READY
);
?>
With these lines of code we register a piece of jQuery (already included with YII) javascript code, using 'myHideEffect' as ID. It will be inserted in the jQuery's ready function (CClientScript::POS_READY). Due to the chainablity of jQuery the little script will run two effects on the .info DIV sequentially:
.animate({opacity: 1.0}, 3000)
Normally this would animate the .info DIV to a full opacity within 3 seconds. But the DIV is already rendered with full opacity upon page load, so calling this effect will just cause a delay for 3 seconds.
.fadeOut("slow")
This is the fadeOut effect which will hide the .info DIV at slow speed.
More information about the jQuery effects can be found here.
Works great!
I tried the following code in my view file. Works Great!
<?php Yii::app()->clientScript->registerScript( 'myHideEffect', '$(".flash-success").animate({opacity: 1.0}, 3000).fadeOut("slow");', CClientScript::POS_READY ); ?> <?php if(Yii::app()->user->hasFlash('success')):?> <div class="flash-success"> <?php echo Yii::app()->user->getFlash('success'); ?> </div> <?php endif; ?>
JavaScript delays
This will not work.
~~~
setTimeout(3000, function(){ $(".info").fadeOut("slow"); });
~~~
This one does.
~~~
setTimeout(function(){ $(".info").fadeOut("slow"); },3000);
~~~
Automated display of flash messages
The main.css file from the default set of CSS files coming with Yii defines these three classes: div.flash-error, div.flash-notice and div.flash-success. You can use them to automate display of flash messages to the user in accordance with their type ("error", "notice" or "success"). Here is how.
Step 1. Put this method into your WebUser class:
/** * @return array flash message keys array */ public function getFlashKeys() { $counters=$this->getState(self::FLASH_COUNTERS); if(!is_array($counters)) return array(); return array_keys($counters); }
Step 2. Put this piece of code into your layout or view where a flash message would be appropriate:
<?php $user=Yii::app()->getUser(); foreach($user->getFlashKeys() as $key): if($user->hasFlash($key)): ?> <div class="flash-<?php echo $key; ?>"> <?php echo $user->getFlash($key); ?> </div> <?php endif; endforeach; ?>
Step 3. Put lines of code similar to these where appropriate to notify the user of the corresponding event types:
Yii::app()->getUser()->setFlash('error','Could not save data to the database.'); Yii::app()->getUser()->setFlash('notice','There was nothing to save.'); Yii::app()->getUser()->setFlash('success','The data was successfully saved to the database.');
Javascript Delays
`$(".info").animate({opacity: 1.0}, 3000).fadeOut("slow");`
The animate call on this line of code is used as a hack to perform a delay. As specified shortly after it was written. However, the one problem with using this method is that it consumes CPU resources for no real purpose. You can use this instead:
~~~
setTimeout(3000, function(){ $(".info").fadeOut("slow"); });
~~~
This method will not consume resources for the delay.
On another note, however. If you want to display information to a user, it is usually recommended that you leave the information on the screen until the user supplies input to say they want it to go away. There is nothing more annoying than having an error message fadeOut before you have time to read the whole thing.
You can do this by put a close image/button/link somewhere in the message area that the user can click and use the following line (assuming the id of your link is 'close_btn':
~~~
$('#close_btn').click(function(){ $(".info").fadeOut("slow"); });
~~~
Update to post by 'sova'
Since v1.1.3 the CWebUser::getFlashes method is available, which makes automatic display of flash messages even easier:
<?php foreach(Yii::app()->user->getFlashes() as $key => $message) { if ($key=='counters') {continue;} echo "<div class='flash-{$key}'>{$message}</div>"; } ?>
Not work with Ajax Validation
On CActiveForm widget, which usually generated by Gii, when the form is submit, there are 2 request, one for sending the data normally from the Submit button, and one for perform Ajax validation.
Strange that the ajax validation request is performed after the normal one. So there is no way to save the Flash session data for 3rd request (the redirect page).
I have to disable ajax validation to make it work.
Since 1.1.3 we can use...
<?php foreach(Yii::app()->user->getFlashes() as $key => $message) { if ($key=='counters') {continue;} //no need next line since 1.1.7 echo "<div class='flash-{$key}'>{$message}</div>"; } ?>
Javascript Delays
jquery delay method
[javascript] $(".info").delay(3000).fadeOut("slow");
autoUpdateFlash
This thing has caused me headache, hope can help others too..
Yii's flash message only persist on first and second request. On the third request it will disappear. To prevent this behavior we must set the CWebUser's autoUpdateFlash to false. That way, the flash message will only deleted after calling getFlash()
'user'=>array( ... 'autoUpdateFlash' => false, // add this line to disable the flash counter ),
Reference : http://www.yiiframework.com/forum/index.php?/topic/21077-flash-messages-and-redirect/
POST_END
When using POST_READY on certain situations, you may notice a initial undesired blink. You can try to fix it, by using CSS and display:none; however, when you have several flash messages to display instead of just one, you have to play with foreach flags and so forth...
I found out that, on certain situations, if instead of POST_READY I use POST_END, no more blinking undesired effect appears.
Hope it saves some time to someone.
Flash Message and Redirect
Hi there!
I still have this problem. Using Yii 1.1.14, I have set the option [code]autoUpdateFlash[/code] to [code]false[/code], but still no flash message after a redirect.
Thanks for the help.
Cheers!
Multiple Flash Messages
I found it possible to pass multiple flash messages via passing an array.
if ($model->load(Yii::$app->request->post())) { // get the uploaded file instance. for multiple file uploads // the following data will return an array $images = UploadedFile::getInstances($model, 'image'); $errors = Array(); foreach($images as $image) { //Save Image //Save Model try{ $model->save(); } catch(db\IntegrityException $e) { $errors[] = $model->name; } } Yii::$app->session->setFlash('error', $errors); return $this->redirect(['index']); }
Using this method you could store multiple flashes for each type, success, error et cetera
I displayed like this (am using kartik\widgets\Alert for prettier errors)
<? $errors = Yii::$app->session->getFlash('error') ?> <? if(isset($errors)) { $base_delay = 0; foreach($errors as $error) { $base_delay += 1500; echo Alert::widget([ 'type' => Alert::TYPE_DANGER, 'title' => 'Error Logo Exists!', 'icon' => 'glyphicon glyphicon-exclamation-sign', 'body' => $error, 'showSeparator' => true, 'delay' => $base_delay, ]); } } ?>
This works really well for me and solves a problem I have had for ages lol.
how to use it when use Ajax button, I need to display flash message after ajax request returned
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.