Re: Multiple layout section override ?

Albert Kam <[email protected]> Mon, 11 Mar 2013 11:56:41 +0700
Newsgroups gmane.comp.web.freemarker.user
Message-ID <CAMT20g934Ng1FeqkSZmwZ0gVpr2k+ckzcbpXZJSJB2CJtzyMLQ@mail.gmail.com>
Thanks for clearing it up Daniel.
I am currently applying the macro solution for the time being as it works
and i have more things to do for now.
I will be posting to this thread again if i manage to find the time to impl
the custom block directive.

Regards from Jakarta,
Albert Kam


On Sun, Mar 10, 2013 at 6:42 PM, Daniel Dekany <[email protected]> wrote:

> Saturday, March 9, 2013, 2:00:38 PM, Albert Kam wrote:
>
> > Thanks for the ideas.
> >
> > I have tried the macro solution from your reply, seems great !
> >
> > the layout file :
> > <#macro defaultHeader>
> > defaultHeader here
> > </#macro>
> >
> > <#macro defaultFooter>
> > defaultFooter here
> > </#macro>
> >
> > <#macro layout header=defaultHeader footer=defaultFooter>
> > <@header />
> > <#nested>
> > <@footer />
> > </#macro>
> >
> > the 'page' file that overrides a header n provide a body as usual:
> > <#macro overrideHeader>
> > header overriden
> > </#macro>
> >
> > <@layout header=overrideHeader>
> > body overriden
> > </@layout>
> >
> > The output is :
> > header overriden
> > body overriden
> > defaultFooter here
> >
> > ------------------
> >
> > I have not tried the java directive yet. I would like to clarify
> > some points before trying it out :
> >
> >> The layout macro need to push a TemplateHashModel into a stack that's
> stored in a custom Environment attribute,
> > How to do this inside the macro, is it by using #assign directive
> > to store to the global variable so it can be fetched later from the
> > TemplateDirectiveModel's Environment via the getGlobalVariable() ?
> > If yes, how do i assign a 'hash' to a global variable ? And i dont
> > see any stack in the Environment api doc.
>
> You can't, or at least, shouldn't implement the more technical parts
> of this in FTL. FTL, being an MVC View language, really just meant to
> get everything ready from the data-model or from a directive/method
> that was implemented in Java. So certainly you need to write a few
> directives like:
>
> - <@my.setBlock name="whatever">output will be captured here</@my.push>
>   which stores the captured output into the top hash of said stack.
>
> - my.blocks.whatever: get an earlier set block from the top hash of
>   the stack.
>
> - For convenience, maybe: <@my.printBlock name="whatever" />
>   which is basically <#noesacpe>${my.blocks.whatever}</#noescape>.
>
> - <@my.collectBlocks>...</@>
>   which pushes a new empty hash into said stack, then pops it at the
>   end
>
> Then can use these when writing macros and just forgat about the
> technical parts.
>
> As of the technical parts... freemarker.core.Environment has a
> set/getCustomAttribute method. There's no restriction regarding the
> type of the attribute value, so there *you* can implement that stacks.
>
> As of the hash thing... My quick idea was that the stack items are
> themselves TemplateHashModelEx instances, so that you can easily
> access them from the templates, but this really and unimportant
> detail, and above I haven't even used it in that form. Because above
> my.blocks is a TemplateHashModelEx that shows the topmost stack item.
>
> Anyway, this should really be a core feature of FreeMarker, but I
> don't think I will have time to implement this in the near future,
> so...
>
> >> then call #nested.
> > This is as simple as providing <#nested> in the macro, correct ?
>
> Yes.
>
> >> Then, @block should capture the content generated inside its body, get
> the topmost TemplateHashModel from said
> > stack, and put the captured content into with block name (like"heading")
> as the key.
> > So, this means that the <#nested> in the layout doesnt produce any
> output at all.
>
> Yes.
>
> > And to produce the header, body, footer, i have to loop all the
> > captured contents stored in the global variable, correct ?
>
> Well, I would put them into that stack that's stored in an Envionment
> attribute, but that's similar to a global variable in its scope and
> life-cycle.
>
> > And if this is so, what is the convenient way to provide a default
> > content for a section that might not be overriden ?
>
> For example, <@my.printBlock name="whatever" /> could have optionally
> nested content that provides the default value.
>
> > Thank you so much !
> >
> >
> > On Sat, Mar 9, 2013 at 7:53 AM, Daniel Dekany <[email protected]>
> wrote:
> > Wednesday, March 6, 2013, 2:46:26 PM, Albert Kam wrote:
> >
> >> I am aware that i can use macros for layouting, for example, a main
> >> layout that contains header, left body section, center body section,
> footer.
> >>
> >> Based on the examples i have googled, like this one here
> >>
> http://wendefer.blogspot.com/2007/09/handy-tip-for-layouts-in-freemarker.html
> ,
> >> i can use <#nested> in the main layout for dynamic values for other
> >> templates that use this main layout macro.
> >>
> >> But in my case, i would like the other templates to be able to
> >> 'override' more than 1 <#nested>, for example, providing the content
> >> of left body section -and- center body section (like apache tiles).
> >>
> >> Is this supported, or maybe is there any other approaches to do this ?
> >
> > Sadly, there's still no built-in solution for this. I have seen two
> > approaches to work this around. First is passing macros to the layout
> > macro:
> >
> >   <#macro myHeading>
> >     ...
> >   </#macro>
> >
> >   <#macro myFooter>
> >     ...
> >   </#macro>
> >
> >   <@myApp.page heading=myHeading body=myFooter>
> >     ... this is the body ...
> >   </@myApp.page>
> >
> > It's kind of noisy though. So I would rather implement this (some
> > deeper FreeMarker knowledge is needed):
> >
> >   <@myApp.page>
> >     <@block name="heading">
> >       ...
> >     </@block>
> >     <@block name="body">
> >       ...
> >     </@block>
> >     <@block name="footer">
> >       ...
> >     </@block>
> >   </@myApp.page>
> >
> > Here @block has to be implemented by you, in Java
> > (TemplateDirectiveModel). The layout macro need to push a
> > TemplateHashModel into a stack that's stored in a custom Environment
> > attribute, then call #nested. Then, @block should capture the content
> > generated inside its body, get the topmost TemplateHashModel from said
> > stack, and put the captured content into with block name (like
> > "heading") as the key.
> >
> > --
> > Best regards,
> >  Daniel Dekany
> >
> >
> >
> ------------------------------------------------------------------------------
> > Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester
> > Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the
> > endpoint security space. For insight on selecting the right partner to
> > tackle endpoint security challenges, access the full report.
> > http://p.sf.net/sfu/symantec-dev2dev
> > _______________________________________________
> > FreeMarker-user mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/freemarker-user
> >
> >
> >
>
> --
> Best regards,
>  Daniel Dekany
>
>
>
> ------------------------------------------------------------------------------
> Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester
> Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the
> endpoint security space. For insight on selecting the right partner to
> tackle endpoint security challenges, access the full report.
> http://p.sf.net/sfu/symantec-dev2dev
> _______________________________________________
> FreeMarker-user mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>



-- 
Do not pursue the past. Do not lose yourself in the future.
The past no longer is. The future has not yet come.
Looking deeply at life as it is in the very here and now,
the practitioner dwells in stability and freedom.
(Thich Nhat Hanh)

------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev

_______________________________________________
FreeMarker-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freemarker-user