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.


Reply via email to