[2.0.2-scala] Is flashing only intended for redirects?

2,101 views
Skip to first unread message

Rintcius Blok

unread,
Jul 18, 2012, 12:46:24 PM7/18/12
to play-fr...@googlegroups.com
I was testing the behaviour of flashing. It seems that it only works with redirects. Is this as intended?
I.e. in the code below the redirect method show the flash text: Flash(Map(success -> redirect))
whereas the noRedirect method shows (when executed first time): Flash(Map()) (NOTE: when re-executing it does show the Flash(Map(success -> no redirect)) since the 1st request gets effective then)

I can explain the behaviour when debugging the HTTP requests and responses, since it:
- first does a "Set-Cookie: PLAY_FLASH=..." in the response
- based on this response, "Cookie: PLAY_FLASH=..." is set; in the NEXT request.

However, I am wondering whether this behaviour is as intended, since it is not so intuitive at first sight.

object MyFlash extends Controller {


  def noRedirect = Action { implicit request =>
    Ok(flash.toString()).flashing("success" -> "no redirect").withHeaders("Content-Type" -> "text/plain")
  }

  def redirect = Action { implicit request =>
    Redirect(routes.MyFlash.redirected).flashing("success" -> "redirect")
  }

  def redirected = Action { implicit request =>
    Ok(flash.toString()).withHeaders("Content-Type" -> "text/plain")
  }
}

Nilanjan

unread,
Jul 18, 2012, 3:47:32 PM7/18/12
to play-fr...@googlegroups.com
Flash is typically used with redirect but its not tied to that. Essentially the Flash scope works exactly like the Session, but with two differences:
  • data are kept for only one request
  • the Flash cookie is not signed, making it possible for the user to modify it.

Let me know if that clarifies the issue.

Nilanjan

Rintcius Blok

unread,
Jul 19, 2012, 4:13:19 AM7/19/12
to play-fr...@googlegroups.com
The problem is that the current implementation (2.0.2) is only useful in case of redirects. For non-redirects it flashes 1 request too late to be useful.
I would like to know if this is a bug or intended behaviour.
If it's a bug I'd be happy to file it in lighthouse. If it's intended then I think the documentation of flash should be improved.

Yann Simon

unread,
Jul 19, 2012, 4:22:53 AM7/19/12
to play-fr...@googlegroups.com
I think it is the intended behaviour.
The purpose of flash is to live the redirect, so that the next GET
request has the needed information.

2012/7/19 Rintcius Blok <rint...@gmail.com>:
> --
> You received this message because you are subscribed to the Google Groups
> "play-framework" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/play-framework/-/B4U0HmJpQWAJ.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to
> play-framewor...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/play-framework?hl=en.

Rintcius Blok

unread,
Jul 19, 2012, 8:46:02 AM7/19/12
to play-fr...@googlegroups.com
I agree that the POST/Redirect/GET is the main reason to start using flash. However it would be nice if it would also work for non-redirects.
For example in Grails 2.1.0 I know flash works as expected for both redirects and non-redirects, whereas in play 2.0.2 it flashes 1 request too late for non-redirects.

Will Sargent

unread,
Jan 10, 2013, 5:35:43 PM1/10/13
to play-fr...@googlegroups.com
Any progress on this?  I've been tripped up by .flashing more than once -- if it only works for Redirects, it should really be a method on Redirect so Ok().flashing doesn't compile.

Will.

Kenny Daniel

unread,
Feb 16, 2013, 7:08:14 PM2/16/13
to play-fr...@googlegroups.com
+1

I think .flashing should work for any type of response, Ok, Redirect, etc. I know this has come up before, so if we for now accept the fact that it only works for redirects, what is the best way to handle a form submission error with flashing-like behavior?

I have a form that gets POSTed. If the form checks out I redirect the user to a new page with Redirect(...).flashing("success" -> "It works"). So far so good.

If the form fails to validate, I want to return Ok(views.html.formPage(formWithErrors)).flashing("error" -> "This doesn't work")

The problem is that if I switch it to a Redirect, I lose form data. If I use Ok, there is no way to use the flash context. I could add parameters to (every) template but that seems uglier than having a flash context.

How are people solving this in practice?

 -- Kenny

Will Sargent

unread,
Feb 16, 2013, 11:02:47 PM2/16/13
to play-fr...@googlegroups.com
On Sat, Feb 16, 2013 at 4:08 PM, Kenny Daniel <plat...@gmail.com> wrote:
> +1
>
> I think .flashing should work for any type of response, Ok, Redirect, etc. I
> know this has come up before, so if we for now accept the fact that it only
> works for redirects, what is the best way to handle a form submission error
> with flashing-like behavior?
>
> I have a form that gets POSTed. If the form checks out I redirect the user
> to a new page with Redirect(...).flashing("success" -> "It works"). So far
> so good.
>
> If the form fails to validate, I want to return
> Ok(views.html.formPage(formWithErrors)).flashing("error" -> "This doesn't
> work")

So the way I think it's supposed to work:

The formWithErrors will show errors when the page is rendered, so you
should see data here:

@formWithErrors.errors.toString

And you can add a special key to the errors list that says "This doesn't work."

Will.

Julien Richard-Foy

unread,
Feb 17, 2013, 7:30:37 AM2/17/13
to play-fr...@googlegroups.com
I had a similar issue a few months ago, here is how I solved it:
Usage examples are available here:

Julien
--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Michael Slinn

unread,
Apr 4, 2013, 5:19:00 PM4/4/13
to play-fr...@googlegroups.com
I keep bumping into this thread. I'd like to show a simple way to use flash with a SimpleResult like Ok, without requiring a redirect. The secret is for your view to accept an implicit Flash, like this:

@(blah: String, whatever: Int)(implicit flash: Flash, request: RequestHeader)
@flash.get("success").map { msg =>
  <p class="text-success">@msg</p>
}
<p>Rest of view goes here</p>


Your controller must finish with something like this:
Ok(views.html.myView("blah", 1234)).flashing("success" -> "This message will be displayed in the view")


That's it!

Mike

Kenny Daniel

unread,
Apr 4, 2013, 6:31:10 PM4/4/13
to play-fr...@googlegroups.com
Mike, your example does not work for me. I WISH it did work like that!

But, I don't really see how it could. You need to modify the flash context before the view gets rendered, in the request, but in your example you are only adding the flash context after the result has already been generated. The effect of .flashing is to sets a cookie for the flash context, and then upon redirecting, that flash context is now part of the request (because it gets sent back by the client). 

The only way I could think of to do it would be to wrap the request before rendering the view.

Saleem Ansari

unread,
May 29, 2014, 2:03:48 AM5/29/14
to play-fr...@googlegroups.com
I am using Play! Framework 2.2 version and I was also facing the same problem.

Since flash is an implicit parameter in the view, I created a new flash object, and passed it. This worked for me. Here is how:

I have created a view clients/new_client.scala.html:

@(clientForm: Form[models.Client])(implicit flash: Flash)

 @flash.get("error").map { errorMessage =>
        <div class="alert-message error">
            <p>
                <strong>Oops!</strong> @errorMessage
            </p>
        </div>
    }

<some/><more/><html/><here/>


And in the Client controller I check if the client entered already exists, then create a flash object and re-render the view.

def add() ....
        val boundForm = clientForm.bindFromRequest
        boundForm.fold(

          // validate rules
          // form has errors
          formWithErrors => {
            log.debug("Form has errors")
            log.debug(formWithErrors.errors.toString)
            Ok(views.html.clients.new_client(formWithErrors)).flashing(
              "error" -> "Form has errors. Please enter correct values.")
          },

          client => {
            // check for duplicate
            log.debug(client.toString)
            models.Clients.get(client.id)(request.dbSession) match {
              case None =>
                // save
                log.debug("Saving new client")
                models.Clients.insert(client)(request.dbSession)
                // redirect to list
                log.debug("redirecting to client list")
                Redirect(routes.Clients.list)
              case Some(c) => // duplicate
                log.debug("Duplicate client entry")
                val flash = play.api.mvc.Flash(Map("error" -> "Please select another id for this client"))
                Ok(views.html.clients.new_client(boundForm)(flash))

            }
          })


And this works for me in both the cases: Redirect and Ok.


Regards,
Saleem

Reply all
Reply to author
Forward
0 new messages