So, with nested snippets you have two basic execution model options: 1) the default, the inner snippets get executed after the outer snippet has executed completely. the outer snippet sees as it's content the original content from the template, complete with lift:Item.points tags and so on. 2) when eager_eval="true" is specified on the outer snippet, the inner snippets get executed completely before the outer snippet gets executed. the outer snippet sees the _result_ of processing the children from the template, so it sees whatever the lift:Item.points snippet gives back.
So, this means that fundamentally you couldn't tell the inner snippet which is the current one, without rewriting the call to the inner snippet (e.g. find the <lift:Item.points> tag and write in an attribute -- this seems like a grody hack) If you really want an inner snippet running _during_ the processing of the outer snippet, I think you need to do that processSurroundAndInclude thing in the outer snippet code. If you're not tied to the inner snippet, then omit it, like this: class Item extends DispatchSnippet { val dispatch: DispatchIt = { case "firstAndSecond" => firstAndSecond } def firstAndSecond(ns: NodeSeq): NodeSeq = List(("first", firstSeqOfThings), ("second", secondSeqOfThings)).flatMap { case (label, items) => bind("item", ns, "which" -> label, "points" -> { (ns: NodeSeq) => items.flatMap { item => bind("point", ns, "name" -> item.name) }) } } And the template would be: <h1>Items</h1> <lift:Item.firstAndSecond> <h2><item:which /></h2> <ul> <item:points> <li><point:name /></li> </item:points> </ul> <item:picture /> </lift:Item.firstAndSecond> If you're concerned about embedding so much code in the snippet (which seems to be why you want to break into multiple snippets?) then just break them out into separate functions, like I showed you in the foreach example. I think it helps to remember that snippets are really just XML -> XML functions, and there's little special about them other than that they can be named in templates. You can always call snippets from other snippets directly (e.g. (new MySnippet).thatSnippet(nodes)), though if you use any stateful stuff in those snippets that depends on the current expansion point (e.g. S.attr) then you'd need to break the snippet into two pieces, e.g. class MySnippet extends DispatchSnippet { val dispatch: DispatchIt = { case "foobar" => foobar } def foobar(ns: NodeSeq): NodeSeq = { S.attr("itemId").map(lookupItemById _) match { case Full(item) => foobar(item)(ns) case _ => error("could not find item -- itemId attribute not given or invalid") } } def foobar(item: ItemModel)(ns: NodeSeq): NodeSeq = bind(...) } Now if you're calling from template, you say <lift:MySnippet.foobar itemId="1234">...</lift:MySnippet.foobar>, but if you're in some other snippet you say MySnippet.foobar(theItem)(...) Hope that helps, -Ross On Dec 23, 2009, at 4:32 PM, Alex Black wrote: > Thanks Ross, I think I get that.. I'm not seeing the full picture yet, > let me show a bit more of my thinking: > > So, extending my previous example, I'd like to write it like this: > > <h1>Items</h1> > > <lift:Item.firstAndSecond> > <h2><item:which></h2> > <ul> > <lift:Item.points> > <li><point:name /> > </lift:Item.points> > </ul> > <lift:item.picture /> > </lift:Item.firstAndSecond> > > // Emit the block twice, once for each item (first,second). > def firstAndSecond(xhtml: NodeSeq): NodeSeq = { > List(first,second).flatMap( item => renderItem(xhtml, item) ) > } > > How then do I implement Item.picture, Item.points to know *which* item > is currently being rendered? > > thx > > - Alex > > > > > > > On Dec 23, 4:18 pm, Ross Mellgren <dri...@gmail.com> wrote: >> S.attr gives you attributes of the current snippet calling tag, e.g. >> >> class Item extends DispatchSnippet { >> val dispatch: DispatchIt = { >> case "points" => points >> } >> >> def points(ns: NodeSeq): NodeSeq = { >> val points = S.attr("item") match { >> case Full("first") => loadFirstListOfPoints() >> case Full("second") => loadSecondListOfPoints() >> case _ => error("missing item attribute or has incorrect >> value") >> } >> >> bind(...) >> } >> >> } >> >> -Ross >> >> On Dec 23, 2009, at 4:07 PM, Alex Black wrote: >> >>> I've got some xhtml blocks in one of my templates that are basically >>> identical, and I'd like to avoid the duplication, by either writing >>> the block once in my template and using a snippet to write it out >>> twice (with different values) or put it in its own template. >> >>> <h1>Items</h1> >> >>> <h2>First</h2> >>> <ul> >>> <lift:Item.firstPoints> >>> <li><point:name /> >>> </lift:Item.firstPoints> >>> </ul> >>> <lift:item.firstPicture /> >> >>> <h2>Second</h2> >>> <ul> >>> <lift:Item.secondPoints> >>> <li><point:name /> >>> </lift:Item.secondPoints> >>> </ul> >>> <lift:item.secondPicture /> >> >>> My question is: If I write this block once, and surround it in a >>> snippet which emits it twice, how can the snippet parameterize the >>> nested snippet calls? >> >>> I realize I could bind the entire block with one snippet call, but >>> because my real blocks are big and complex I'd like to keep the many >>> snippet calls per block. >> >>> So, more specifically, how can i write <lift:Item.secondPoints> and >>> <lift:item.firstPoints> more like this: <lift:item.points >>> item="@curItem"> >> >>> thx >> >>> - Alex >> >>> -- >> >>> You received this message because you are subscribed to the Google >>> Groups "Lift" group. >>> To post to this group, send email to lift...@googlegroups.com. >>> To unsubscribe from this group, send email to >>> liftweb+unsubscr...@googlegroups.com >>> . >>> For more options, visit this group >>> athttp://groups.google.com/group/liftweb?hl=en >>> . > > -- > > You received this message because you are subscribed to the Google > Groups "Lift" group. > To post to this group, send email to lift...@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscr...@googlegroups.com > . > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en > . > > -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.