"stateful snippet" or something else - set variables before displaying

34 views
Skip to first unread message

Andrzej Skalski

unread,
Mar 23, 2015, 12:09:17 PM3/23/15
to lif...@googlegroups.com
Hi,

I am writing a web app that multiple times requires a snippet to work with some data. I used to do this with SessionVars (not sure if that was a right idea)

 
{
   
SHtml.link("/teacher_edit_exam",
       
() => ASExamFormulaEditorSnippet.varFormulaToEdit(Full(f)),
       
Text(f.getCaption))
}

then I discovered, that this method is being re-called every refresh, which is bad when I would like to use a constructor inside it. Each time user reloads a page, it receives a fresh instance of - say - an exam sheet. Not very good. So I tried with stateful snippets:

{
    val t
: ExamTakerSnippet = new ExamTakerSnippet
    t
.link("/take_exam", () => { t.varExamToTake = Full(ExamTake(user, f)) }, Text("start"))
}


but this for some reason doesn't even set the variable. It turnes out to be Empty on display.

What is the preffered way to set snippet's data before displaying it, so the data survives refreshing web page?

Kindest Regards
Andrzej Skalski

Joe Barnes

unread,
Mar 23, 2015, 1:26:09 PM3/23/15
to lif...@googlegroups.com
Hello Andrzej!

Let me make sure I understand.  The two code blocks you have here are two attempts at writing a snippet.  And you want some object (it is unclear to me which object you mean) to be instantiated once and reused each time the snippet is rendered?

This all depends on what you want the scope of that object to be.  SessionVar is the right thing if it should be instantiated once for a user session.  I would place the exam sheet in a SessionVar, and let the snippet retrieve the object from there.  

I think I will be able to help a little more if you can include more of the relevant code so I can get a more complete picture of what you hope to achieve.

Joe

Andrzej Skalski

unread,
Mar 23, 2015, 2:06:57 PM3/23/15
to lif...@googlegroups.com
Hi Joe,

I wish I could share some portion of this code, but I am afraid that my client would not accept it.

Yes, these two portions of code are my attempts to generate a link to a separate view, on which the snippet is displayed. A link, that will put the snippet into a desired state, by inserting some input data. The first one works, but sets the field again and again each refresh (F5) of destination site. That is sometimes acceptable, but sometimes it's not. For instance, if I want to create a new database object (to store exam immediate state), a refresh would cause the old being replaced with a fresh instance.

The latter call was my attempt to rewrite one of the snippets to StatefulSnippet, using some tutorials I found. It starts with a constructor (since stateful snippet is a class, not object) after which I try to set a field on link click. This does not work as expected - after going to /take_exam, the snippet displays information that the field has not been set. I don't know why.

So my question is quite open. I can either fix the original approach with SessionVars, but then I need a way to distinguish between a initial display and refreshes, to stop the object holding state from being overridden.
The other approach is to learn how to use stateful snippets (this is probably more advantageous), but there I am stuck with "how to set the state before user sees the snippet". Of course depending on which instance of link user clicks, I would like to be able to use different input data to snippet - otherwise I would just hardcode it.

I tried to google some samples on github, but I haven't found either a StatefulSnippet.link or StatefulSnippet.redirectTo example, just the code of the snippet itself.

Is that a better description of my question? I apologize for not being very specific - I am still learning liftweb, so I am not sure if I even look into right direction.

Kindest Regards
Andrzej Skalski

Antonio Salazar Cardozo

unread,
Mar 23, 2015, 2:57:04 PM3/23/15
to lif...@googlegroups.com
Lift's Wizard may be of interest to you, but I haven't used it, so I don't know exactly how it works—I just
know it's meant for managing multi-page flows like this one.

That said, you can try wrapping SHtml.link with S.oneShot:

S.oneShot {
    SHtml.link("/teacher_edit_exam",
        () => ASExamFormulaEditorSnippet.varFormulaToEdit(Full(f)),
        Text(f.getCaption))
}

This will make the function that's bound in the SHtml.link only run once, and future reloads and such
will fail to load.
Thanks,
Antonio

Andrzej Skalski

unread,
Mar 25, 2015, 8:22:33 AM3/25/15
to lif...@googlegroups.com
Thanks, but I think that reloading a webpage is something natural, and I have to take it into account.

Instead, I just checked Snippet's state in body of bound function, and if the value was set I refrain from overriding it.

Kindest Regards
Andrzej Skalski

Antonio Salazar Cardozo

unread,
Mar 25, 2015, 3:17:50 PM3/25/15
to lif...@googlegroups.com
Sorry, I was in a hurry there… Future reloads won't fail to load, they just won't run the function.
Thanks,
Antonio

Andrzej Skalski

unread,
Mar 25, 2015, 4:21:53 PM3/25/15
to lif...@googlegroups.com
Oh, than it's a useful piece of know-how here, thank you!

Andrzej
Reply all
Reply to author
Forward
0 new messages