Setting S.error in SHtml.text's assignment-callback and accessing the errors in a redirect-after-post

58 views
Skip to first unread message

Andreas Joseph Krogh

unread,
May 10, 2011, 7:56:26 AM5/10/11
to liftweb
Hi.
In relation to http://groups.google.com/group/liftweb/browse_thread/thread/0010c68e39311adf?hl=en I'm wondering how to set an S.error (with a dynamically generated, unique ID) in a form-element's assignment-callback and access it in a subsequent page-rendering after the form is posted (no AJAX), using redirect-after-post.

I really need the "id" to use for the error-messge to be generated and uniqe so I thought of using nextFuncName to get such an ID, but I have problems grasping how to put it all together.

Say I have this code for rendering a SHtml.text:

-----------------------------
class MySnippet extends StatefulSnippet
...

def renderTextInput(entry: SomeEntry) = {
SHtml.text(entry.stuff, (s) => {
if (s.trim.matches("^\\d+:\\d+$")) entry.stuff = s.trim
else {
val id = nextFuncName // Need this ID to survive a redirect-after-post somehow
S.error(id, "Error in input: "+s)
}
})

// On the subsequent page-rendering, after the form is submitted, then redirected,
// the text-input is rendered again (snippet calling renderTextInput) and S.errors
// should hold all errors, but I need a way to access the ID

if (!S.messagesById(idSetInAssighmentCallback)(S.errors).isEmpty) {
println("Errors found: " + S.messagesById(idSetInAssighmentCallback)(S.errors))
}
}

I have a submit-button mapped like this:
".save" #> SHtml.submit("Save", () => save())

private def save() {
if (S.errors.isEmpty) {
// save it
}
S.redirectTo(S.uri)
}
-----------------------------

So, the work-flow is:
  1. Fill in some values in the form
  2. Click the "Save"-button which POSTs the form (no AJAX)
  3. The save() method is executed on the same instance of the snippet as the previous page-rendering (Lift has inserted a hidden-field to be able to look-up my StatefulSnippet), then it redirects to the same page(uri). After the redirect the snippet is fresh (new instance), not the same as the previous one despite it being stateful...
  4. The page renders and here I'd like to show the errors registered in the assignment-callback of SHtml.text
Anybody knows a way to accomplish this? It seems I'm missing some key issue here as this is a common pattern in web-application development.

Any help is very much appreciated, thanks.

--
Andreas Joseph Krogh <and...@officenet.no>
Senior Software Developer / CTO
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Tomáš Dvořák

unread,
May 19, 2011, 4:59:39 PM5/19/11
to Lift
I'm new to lift, so maybe I'm completely wrong, but it seems to me
that the problem is in step 3 - you expect the snippet to be the same
instance (in which case you could just hold the id as an instance
variable), but you get another instance instead? If this is the
problem, I think using snippetInstance.redirectTo instead of
S.redirectTo will solve your issue.

Best regards,
Tomas Dvorak

On May 10, 1:56 pm, Andreas Joseph Krogh <andreas.kr...@gmail.com>
wrote:
> Hi.
> In relation tohttp://groups.google.com/group/liftweb/browse_thread/thread/0010c68e3...
> I'm
> wondering how to set an S.error (with a dynamically generated, unique ID) in
> a form-element's assignment-callback and access it in a subsequent
> page-rendering after the form is posted (no AJAX), using
> redirect-after-post.
>
> I really need the "id" to use for the error-messge to be generated and uniqe
> so I thought of using nextFuncName to get such an ID, but I have problems
> grasping how to put it all together.
>
> Say I have this code for rendering a SHtml.text:
>
> -----------------------------
> class MySnippet extends StatefulSnippet
> ...
>
> def renderTextInput(entry: SomeEntry) = {
> SHtml.text(entry.stuff, (s) => {
>  if (s.trim.matches("^\\d+:\\d+$")) entry.stuff = s.trim
>  else {
>  val id = nextFuncName *// Need this ID to survive a redirect-after-post
> somehow*
>  S.error(id, "Error in input: "+s)
>  }})
>
> *
> *
> * // On the subsequent page-rendering, after the form is submitted, then
> redirected,*
> * // the text-input is rendered again (snippet calling renderTextInput) and
> S.errors*
> * // should hold all errors, but I need a way to access the ID*
>
> if (!S.messagesById(*idSetInAssighmentCallback*)(S.errors).isEmpty) {
>  println("Errors found: " + S.messagesById(*idSetInAssighmentCallback*
> )(S.errors))
>
> }
> }
>
> I have a submit-button mapped like this:
> ".save" #> SHtml.submit("Save", () => save())
>
> private def save() {
> if (S.errors.isEmpty) {
> // save it}
> S.redirectTo(S.uri)
> }
>
> -----------------------------
>
> So, the work-flow is:
>
>    1. Fill in some values in the form
>    2. Click the "Save"-button which POSTs the form (no AJAX)
>    3. The save() method is executed on the same instance of the snippet as
>    the previous page-rendering (Lift has inserted a hidden-field to be able to
>    look-up my StatefulSnippet), then it redirects to the same page(uri). After
>    the redirect the snippet is fresh (new instance), not the same as the
>    previous one despite it being stateful...
>    4. The page renders and here I'd like to show the errors registered in
>    the assignment-callback of SHtml.text
>
> Anybody knows a way to accomplish this? It seems I'm missing some key issue
> here as this is a common pattern in web-application development.
>
> Any help is very much appreciated, thanks.
>
> --
> Andreas Joseph Krogh <andr...@officenet.no>

David Pollak

unread,
May 20, 2011, 7:34:21 PM5/20/11
to lif...@googlegroups.com

Can you turn this into a simple example (see Posting example code | Lift Space | Assembla ) and I'll try to enhance the code to do what you want it to do?
 
It seems I'm missing some key issue here as this is a common pattern in web-application development.

Any help is very much appreciated, thanks.

--
Andreas Joseph Krogh <and...@officenet.no>
Senior Software Developer / CTO
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.



--
Lift, the simply functional web framework http://liftweb.net

Andreas Joseph Krogh

unread,
May 21, 2011, 12:17:27 PM5/21/11
to lif...@googlegroups.com
On 05/19/2011 10:59 PM, Tomáš Dvořák wrote:
> I'm new to lift, so maybe I'm completely wrong, but it seems to me
> that the problem is in step 3 - you expect the snippet to be the same
> instance (in which case you could just hold the id as an instance
> variable), but you get another instance instead? If this is the
> problem, I think using snippetInstance.redirectTo instead of
> S.redirectTo will solve your issue.

Yes, calling StatefulSnippet.redirectTo() instead of S.redirectTo would
solve my problem. But to be spec-compliant I want to use seeOther (303)
so I ended up using:

S.seeOther(S.uri, () => {
registerThisSnippet() // For redirecting to the same instance of this
snippet
}

Originally I managed state using RequestVars but using StatefulSnippet
with registerThisSnippet() and just holding stuff in member-variables is
much easier and fits my needs just fine, as I dont share any state with
other snippets here.

I don't have commit-rights to add seeOther to StatefulSnippet but it's a
very simple addition:

StatefulSnippet already has:
def redirectTo(where: String) = S.redirectTo(where, registerThisSnippet)

So it's a simple matter of adding:
def seeOther(where: String) = S.seeOther(where, registerThisSnippet)

Any committer up to adding this?

--
Andreas Joseph Krogh <and...@officenet.no>

Andreas Joseph Krogh

unread,
May 21, 2011, 12:28:39 PM5/21/11
to lif...@googlegroups.com
Actually you've shown me the path already so my code works now thanks to the excellent feedback I get from this community, especially you David.

Thanks again for helping out!

I now have field-validation on dynamically generated fields on a page using Oval (oval.sf.net). If field-errors occur the errors are shown on each invalid field and all is post-redirect-get (http-response-code 303). I pretty much have all I need in place now so I must find time to put in place an example and put it up on github. I think what I have in place is pretty useful to JAVA/JEE-migrates who want to use Lift together with DDD and Spring/JPA.

David Pollak

unread,
May 21, 2011, 12:58:44 PM5/21/11
to lif...@googlegroups.com

Yes.  Please open a ticket.  You can also add this as a trait today which you can compose into the StatefulSnippet class.

Looking forward to your example code and thank you very much for contributing back to the community.
 

--
Andreas Joseph Krogh <and...@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                       |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909 56 963 |                                             |
------------------------+---------------------------------------------+

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.

Andreas Joseph Krogh

unread,
May 21, 2011, 2:09:47 PM5/21/11
to lif...@googlegroups.com

David Pollak

unread,
May 21, 2011, 2:29:45 PM5/21/11
to lif...@googlegroups.com
Thanks!!

> Andreas Joseph Krogh <and...@officenet.no> <and...@officenet.no>


> Senior Software Developer / CTO
> Public key: http://home.officenet.no/~andreak/public_key.asc
> ------------------------+---------------------------------------------+
> OfficeNet AS | The most difficult thing in the world is to |
> Rosenholmveien 25 | know how to do a thing and to watch |
> 1414 Trollåsen | somebody else doing it wrong, without |
> NORWAY | comment. |
> Org.nr: NO 981 479 076 | |
> | |
> Tlf: +47 24 15 38 90 | |
> Fax: +47 24 15 38 91 | |
> Mobile: +47 909 56 963 | |
> ------------------------+---------------------------------------------+
>
>
>
>
>
>

Reply all
Reply to author
Forward
0 new messages