Also if you need to do a foreach in the middle of a snippet (say in the previous example there was a header row that is also bound by the snippet), the right side of a binding (the part after the arrow) can be a function from NodeSeq to NodeSeq, so you can nest binds, and make that function do a flatMap.
------------------------------------- Erkki Lindpere<[email protected]> wrote: Thanks again for the advice, this was about 25 times faster than what I originally showed! Erkki On Dec 23, 8:59 pm, Ross Mellgren <[email protected]> wrote: > Well, if that's the case then you could do it something like this: > > object MySnippet { > /** Function that binds fields of a single ModelObj */ > def bindModelObj(ns: NodeSeq)(model: ModelObj) = > bind("model", ns, "field1" -> model.field1, "field2" -> > model.field2) > > } > > class MySnippet extends DispatchSnippet { > import MySnippet.bindModelObj > > val dispatch: DispatchIt = { > case "forEach" => forEach > case "justOne" => justOne > } > > def forEach(ns: NodeSeq): NodeSeq = > somehowGetAListOfModelObjects().flatMap(bindModelObj(ns) _) > > def justOne(ns: NodeSeq): NodeSeq = > bindModelObj(ns)(somehowGetJustOneModelObject()) > > } > > And then in your snippet you can also have reuse (I don't know how > efficient this is): > > <lift:MySnippet.forEach> > <model:field1 /> > <model:field2 /> > </lift:MySnippet.forEach> > > <lift:MySnippet.justOne> > <model:field1 /> > <model:field2 /> > </lift:MySnippet.justOne> > > If you have the same rendering for each object, you could use > eager_eval and embed: > > <lift:MySnippet.forEach eager_eval="true"> > <lift:embed what="modelobject" /> > </lift:MySnippet.forEach> > > <lift:MySnippet.justOne eager_eval="true"> > <lift:embed what="modelobject" /> > </lift:MySnippet.justOne> > > -Ross > > On Dec 23, 2009, at 1:51 PM, Erkki Lindpere wrote: > > > Well, I'd prefer to keep different concerns separated. Iterating over > > that list is not the only case where I render those objects, that's > > why I want the rendering of these objects to be separated into their > > own template. > > > But maybe I'll change my mind. Doing it like you suggested is probably > > faster too. > > > Erkki L > > > On Dec 23, 8:31 pm, Ross Mellgren <[email protected]> wrote: > >> S.session.get.processSurroundAndInclude has a couple issues, first is > >> that it seems to be a much larger stick than you need, and the other > >> reason is that you are using "get" (which is for Option, I presume > >> you > >> mean open_!, since S.session is a box) which is not safe -- it will > >> throw NPE in the case where a session is not available. > > >> I think the more idiomatic way is probably more like > > >> def forEachMsg(in: NodeSeq): NodeSeq = { > >> val msgs = somehowGetAListOfModelObjects() > >> msgs.flatMap { msg => > >> bind("msg", in, "field1" -> msg.field1, "field2" -> > >> msg.field2); > >> } > > >> } > > >> And then inline at the call side: > > >> <lift:blabla.forEachMsg> > >> <msg:field1 /> > >> <msg:field2 /> > >> </lift:blabla.forEachMsg> > > >> Is there something peculiar about your use case where you really want > >> to do lift:embed and so on? > > >> -Ross > > >> On Dec 23, 2009, at 1:26 PM, Erkki Lindpere wrote: > > >>> This has probably come up previously, but I couldn't find anything > >>> even though I think a couple of days ago I read about something > >>> similar: > > >>> I want to do a snippet that behaves similarly to JSTL-s forEach tag. > >>> Not exactly the same, but the idea is that it gets some list of > >>> model > >>> objects, then goes through it element by element and processes the > >>> input NodeSeq for each element. What I came up with is this: > > >>> def foreach(in: NodeSeq) = { > >>> val msgs = somehowGetAListOfModelObjects(); > >>> msgs.flatMap { msg => > >>> // set the current object (CurrentMessage is a ThreadLocal) > >>> CurrentMessage.set(msg) > >>> // process the contents, with the current object in scope > >>> S.session.get.processSurroundAndInclude("", in) > >>> } > >>> } > > >>> And it's called like this: > >>> <lift:blabla.foreach> > >>> <lift:embed what="message.html" /> > >>> </lift:blabla.foreach> > > >>> Is there a more correct solution to this? > > >>> -- > > >>> 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 > >>> 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 [email protected]. > > To unsubscribe from this group, send email to > > [email protected] > > . > > 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 [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=en. -- 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=en.
