On Thu, Nov 19, 2009 at 2:52 PM, Chris Lewis <[email protected]> wrote: > Classic use case: a user chooses to view/edit and object by clicking on > a link. This causes the app to fetch an edit view (form) and render it > asynchronously, probably rendering it as a modal dialog. To specify the > case a bit more, consider a table of like objects that allows you to > edit them (orders or accounts). As far as the user experience, clicking > edit for one would yield the same edit form as any other - only the > contents (the target of the edit) would change. > > Normal ajax forms in lift are simple - just wrap the bind in an ajax > form (http://is.gd/4Z61Z) and you get an async submit with essentially > the same template code. > > But what about ajax forms delivered by ajax? What's the best way to > implement this in lift? It seems like there are two routes: client and > server-based. > > > 1) In the client-based approach, I can declare an invisible form in the > template, as well as write some static javascript to do the heavy > lifting (no pun intended). This JS would be responsible for receiving > the data representing the object to edit from the server as json, > unpacking it into the form for editing, rendering the form, handling the > submit as ajax, and finally hiding the form. > > This means writing a good bit more JS by hand, but it keeps the > (compiled) snippet code smaller. Ordinarily I'd see that as good, but > more and more snippets seem like they are intended for such heavy view > meddling. > > > 2) The server-based approach would require very little of the main > template: basically just a containing element (w/ dom id) to host the > delivered form. The snippet itself would yield a form on an ajax call > via SetHtml. It would also have to set up the handlers and populate the > form contents with the target object. > > This is the part that I'm not clear on. I know I can just inline the XML > with bind points as if it were in a form, but that just feels strange. > Would it make more sense to use an external template, similar to a rails > partial? Is there a template loading facility for this? > > Thanks for any and all input. > > chris
I use the second style, to great effect, in Lift - except I use net.liftweb.http.TemplateFinder.findAnyTemplate to get the NodeSeq representing the template instead of inlining the XML, and then use a normal call to bind. It works a treat. There are a couple of utility traits that I use to make this even cleaner; I don't have time to detail how they're used at the moment but maybe you can get a little bit of an idea by looking at the types. One of these days I'll clean these up into something truly reusable (these rely on the bindings stuff I detailed on my blog at http://logji.blogspot.com/2009/09/composable-bindings-in-lift.html with a couple of extra things, tbind and the Templated trait. def tbind(x: Binding with Templated): NodeSeq = x.bind(x.template) trait Templated { def template: List[String] } trait Form[T] { def onSubmit: Unit = process def process: T } trait FormSnippets { this: StatefulSnippet => var actionBinding: Binding with Templated = _ var editFormBinding: Binding with Templated = _ lazy val dispatch: DispatchIt = { case "actionSelect" => actionBinding case "editForm" => editFormBinding } def ajaxify(b: Binding with Templated with Form[_], clientOnSubmit: JsCmd, serverRedirect: Option[String]) = new Binding with Templated { override val template = b.template override def apply(xhtml: NodeSeq): NodeSeq = { def serverOnSubmit: JsCmd = { b.onSubmit serverRedirect.map(where => RedirectTo(where)). getOrElse(SetHtml("action_selector", tbind(actionBinding)) & SetHtml("edit_form", tbind(editFormBinding))) } ajaxForm(b.apply(xhtml) ++ hidden(serverOnSubmit _), clientOnSubmit) } } } Kris -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/liftweb?hl=.
