How to use RequestVar for AJAX?

33 views
Skip to first unread message

BigFool

unread,
Mar 19, 2010, 12:30:43 AM3/19/10
to Lift
I read from comments of it and it says:
"RequestVars maintain their value throughout the duration of the
current HTTP
request and any callbacks for servicing AJAX calls associated with
the rendered page.
RequestVar instances have no value at the beginning of request
servicing (excluding
AJAX callbacks) and their value is discarded at the end of request
processing.
They are commonly used to share values across many snippets."


I am very curious about how to share AJAX callbacks across different
snippets, how can we do that by RequestVar, is there any example about
it?

Timothy Perrett

unread,
Mar 19, 2010, 7:27:20 AM3/19/10
to Lift
Whats your use case for sharing an AJAX callback function?

Cheers, Tim

BigFool

unread,
Mar 19, 2010, 10:54:03 AM3/19/10
to Lift
Given I have two snippets in the same page, one to show a list of
articles and one to show the edit form of a chozen article. My
requirement is that when I hit one article in list, the edit form will
repaint and when I submit the edit form the list also will repaint.

My current solution is just to put the whole things in one snippet
which seems like a mess as below (I tailored so many details to make
it readable):

def render (xhtml : NodeSeq) : NodeSeq = {
var a=new Article
val listTemplate = chooseTemplate("article", "list", xhtml );
val editTemplate = chooseTemplate("article", "edit", xhtml );

def bindList(xhl:NodeSeq): NodeSeq = {
getAllArticles().flatMap(article =>
bind("article", xhl,
"article" -> SHtml.a(() => {
a=article
SetHtml("article_edit", bindEdit(editTemplate))
} ,Text(article.title)
)
)
}

def bindEdit(xhl:NodeSeq): NodeSeq = {
ajaxForm(
bind("article", xhl,
"title" -> text(a.title, a.title=_),
"comment" -> textarea(a.comment, a.comment=_),
"submit" -> ajaxSubmit("Save", () => ajaxSave),
)
)
}

def ajaxSave ={
Model.mergeAndFlush(a)
SetHtml("article_list", bindList(listTemplate))
}

// default binding
bind("article", xhtml,
"list" -> bindList _,
"edit" -> bindEdit _
)
}

All I wanna do is to separate the edit and list into different
snippets but make they can repaint each other by AJAX call

David Pollak

unread,
Mar 19, 2010, 1:00:15 PM3/19/10
to lif...@googlegroups.com

If your ajax function in the List snippet calls bindEdit (in a separate snippet) and passes a function to redraw the page on completion, then you can separate the list and edit.  Does that make sense or do you need a code example?
 

On Mar 19, 7:27 pm, Timothy Perrett <timo...@getintheloop.eu> wrote:
> Whats your use case for sharing an AJAX callback function?
>
> Cheers, Tim
>
> On Mar 19, 4:30 am, BigFool <nanfan...@gmail.com> wrote:
>
> > I read from comments of it and it says:
> >  "RequestVars maintain their value throughout the duration of the
> > current HTTP
> >  request and any callbacks for servicing AJAX calls associated with
> > the rendered page.
> >  RequestVar instances have no value at the beginning of request
> > servicing (excluding
> >  AJAX callbacks) and their value is discarded at the end of request
> > processing.
> >  They are commonly used to share values across many snippets."
>
> > I am very curious about how to share AJAX callbacks across different
> > snippets, how can we do that by RequestVar, is there any example about
> > it?

--
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
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

BigFool

unread,
Mar 20, 2010, 2:26:39 AM3/20/10
to Lift
I just wanna separate the bindEdit and bindList into different
snippits and they can call each other by AJAX and not refresh the
whole page. Can I do that? I would appreciate it if there is code
example.

On Mar 20, 1:00 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:

> > liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>


> > .
> > For more options, visit this group at
> >http://groups.google.com/group/liftweb?hl=en.
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net

> Beginning Scalahttp://www.apress.com/book/view/1430219890

David Pollak

unread,
Mar 20, 2010, 12:18:13 PM3/20/10
to lif...@googlegroups.com
On Fri, Mar 19, 2010 at 11:26 PM, BigFool <nanf...@gmail.com> wrote:
I just wanna separate the bindEdit and bindList into different
snippits and they can call each other by AJAX and not refresh the
whole page. Can I do that?

As I said, yes.  I suggested passing a function that does the list redraw from the ajax link to the method that displays the edit field.  Did you try that?  If so, where did you get hung up?
 
I would appreciate it if there is code
example.

I'll put together an example for you after I understand how far you've gotten trying to implement my suggestion.  Why?  I can write Lift code all day long, but I prefer to teach people the concepts that way they become more proficient with Lift and become better teachers of Lift.  So, if I understand where you're getting stuck based on my suggestion, then I can better teach you (focus on the one or two concepts that are in your way) and I can get a better understanding of where people generally get stuck so that we can build easier stuff into Lift.

Thanks,

David

 
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
Beginning Scala http://www.apress.com/book/view/1430219890

BigFool

unread,
Mar 22, 2010, 4:22:03 AM3/22/10
to Lift
I guess what you mean is that when list snippet redraw edit it pass it
self so that the edit snippet know to to redraw list, and same as edit
snippet. But the two snippets just show in the same page, how can the
list know how to draw the edit form for the first time. I have tried
code like below:

def list (xhtml : NodeSeq) : NodeSeq = {
val editTemplate = ???? // how to get editTemplate


val listTemplate = chooseTemplate("article", "list", xhtml );

def reDrawEdit(a:Article, drawList:()=>JsCmd) = {
SetHtml("article_edit", bindEdit(editTemplate,a, drawList))
}
def reDrawList = {


SetHtml("article_list", bindList(listTemplate))
}
// default binding
bind("article", xhtml,

"list" -> (x:NodeSeq) => bindList(x, reDrawEdit, reDrawList),
)
}

private def bindList(xhl:NodeSeq, reDrawEdit: Article => JsCmd,
drawList: () => JsCmd): NodeSeq = {


getAllArticles().flatMap(article =>
bind("article", xhl,

"article" -> SHtml.a(() => { reDrawEdit(article,
drawList )} ,Text(article.title)
)
)
}

def edit(xhtml : NodeSeq) : NodeSeq = {
...
}

private def bindEdit(xhl:NodeSeq, a:Articel, reDrawList: () => JsCmd):
NodeSeq = {
...
}


I just don't know how to get the editTemplate for the first time. Only
thing I can get now is to hardcode it for list for the first time but
that is definitely awkward.

On Mar 21, 12:18 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:

> > <liftweb%2Bunsu...@googlegroups.com<liftweb%252Buns...@googlegroups.com>

David Pollak

unread,
Mar 22, 2010, 4:28:25 PM3/22/10
to lif...@googlegroups.com
Okay,

I've enclosed an example.

The list drawing method does:

  def list(xml: NodeSeq): NodeSeq = {
    val setHtmlId = S.attr("the_id")

    def doRedraw: JsCmd = setHtmlId match {
      case Full(id) => SetHtml(id, drawIt)
      case _ => Noop
    }

    func = Full(doRedraw _) // capture the function for the add method

    def drawIt(): NodeSeq =
    MyInfo.is.flatMap{ info =>
      bind("info", xml,
           "name" -> info.name,
           "age" -> info.age.toString,
           "edit" -> doAjaxButton("_jsdialog_edit", () => S.mapSnippet("EditInfo", EditInfo(info, doRedraw))) _,
           "delete" -> doAjaxButton("_jsdialog_confirm", () => S.mapSnippet("DeleteInfo", DeleteInfo(info, doRedraw)) ) _)
    }

    drawIt()
  }

We create a drawIt() inner method.  That method is bound to current scope (the xml passed in).  We pass the function (via the doRedraw method invocation) to the creation of a snippet handler (see the mapSnippet).

So, our EditInfo snippet looks like:

class EditInfo {
  def render(xml: NodeSeq): NodeSeq = EditInfo(Info("", 0), Noop)(xml)
}

object EditInfo {
  def apply(info: Info, redraw: => JsCmd) =
  (xml: NodeSeq) => {
    bind("info", xml,
         "name" -> text(info.name, s => info.name = s),
         "age" -> text(info.age.toString, s => asInt(s).foreach(i => info.age = i)),
         "submit" -> ((nodes: NodeSeq) => (<input type="submit" value={nodes}/> ++ hidden( () => {
              info.save ; Unblock & redraw})): NodeSeq)
    )
  }
}

So, EditInfo.apply creates a function bound to a given Info object and a pass-by-name redraw which is invoked when the editing is done.

There's no use of RequestVars.  There's only one bit of explicit state for the Ajax add redraw function.

Does this help?

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
Beginning Scala http://www.apress.com/book/view/1430219890
editjax.tgz
Reply all
Reply to author
Forward
0 new messages