Omid Monshizadeh
Omid Monshizadeh

Reputation: 1534

How to pass variables to parent parent template

I'm trying to design the structor for a page with multiple level of nesting, some thing like:

[base-template]

      ||
      \/

[layout-template]

      ||
      \/

[page-template]

base-template is the master template which I used to implement the skeleton of a page, and I have some layout specific html which is implemented in layout-template. (each layout has some JavaScript and CSS files) Then in each page I import a proper layout and again each page has its own CSS and JavaScript files.

I need to set required css/js file in each layout and page and base template should add css files to the head and js files to the body. I'm trying to accomplish this by using macros but can not get what I need.

Here is the example that explains the use case:

[base-template]

<#macro skeleton>
  <!DOCTYPE html>
    ...
    ...css files...
    <get some more css>
    ...
    <#nested>
    ...js files...
    <get some more js>
  </html>
</#macro>

[layout-template]

<#import "base.ftl" as template>
<set some more css for layout>
<set some more js for layout>
<#macro layout>
  <@template.skeleton>
    <div>
      ... some html in layout ...
      <#nested>
      ... some html in layout ...
    </div>
  </@template.skeleton>
</#macro>

[page-template]

<#import "layout.ftl" as template>
<set some more css for page>
<set some more js for page>
<#macro layout>
  <@template.layout>
    <div>
      ... some html for a page ...
    </div>
  </@template.layout>
</#macro>

I appreciate any helps and feedbacks.

Upvotes: 0

Views: 2432

Answers (2)

ddekany
ddekany

Reputation: 31112

One approach is passing down the list of scripts and style sheets as shown by Goose. Another is defining macros like this:

<#macro registerScripts scripts...>
  <#if !registered_scripts??>
    <#assign registered_scripts = scripts>
  <#else>
    <#assign registered_scripts = scripts + registered_scripts>
  </#if>
</#macro>

<#macro insertScripts>
  <#list registered_scripts as script>
    <script src="/scripts/${script}.js"></script>
  </#list>
</#macro>

Say, you #import the above template as template. Then where you say <set some more js for layout> in your question, you do:

<@template.registerScripts 'foo', 'bar' />

and then in base-template to insert the scripts:

<@template.insertScripts />

Upvotes: 0

Goose
Goose

Reputation: 831

It's not pretty but you could do something like this. Create a sequence of files to add. Concatenate additional files in required templates. This list is then split and files added.

The call to pageLayout can omit the scripts or styles parameters if additional files aren't required. If a template doesn't require additional files then just pass the scripts through without concatenating anything (scripts=scripts).

You would need to modify the example if you want to handle css and js files from various locations.

Edited to use sequence instead of csv

<@pageLayout scripts=["a", "b"]>
    <div>
        bah blah blah
    </div>
</@pageLayout>

<#macro pageLayout scripts=[] styles=[]>
    <@layout scripts=scripts+["pag-a", "pag-b"] styles=styles+["pag-A", "pag-B"]>
        <div>
            Start of pageLayout
            <#nested>
            End of pageLayout
        </div>
    </@layout>
</#macro>

<#macro layout scripts styles>
    <@skeleton scripts=scripts+["lay-a", "lay-b"] styles=styles+["lay-A", "lay-B"]>
        <div>
            Start of layout
            <#nested>
            End of layout
        </div>
    </@skeleton>
</#macro>

<#macro skeleton scripts styles>
    <!DOCTYPE html>
    <html>
        <head>
            <#list (styles+["skel-A", "skel-B"]) as style>
                <link rel="stylesheet" href="/styles/${style}.css">
            </#list>
            <#list (scripts+["skel-a", "skel-b"]) as script>
                <script src="/scripts/${script}.js"></script>
            </#list>
        </head>
        <body>
            Start of skeleton
            <#nested>
            End of skeleton
        </body>
    </html>
</#macro>

Output

<!DOCTYPE html>
<html>
    <head>

        <link rel="stylesheet" href="/styles/pag-A.css">
        <link rel="stylesheet" href="/styles/pag-B.css">
        <link rel="stylesheet" href="/styles/lay-A.css">
        <link rel="stylesheet" href="/styles/lay-B.css">
        <link rel="stylesheet" href="/styles/skel-A.css">
        <link rel="stylesheet" href="/styles/skel-B.css">
        <script src="/scripts/a.js"></script>
        <script src="/scripts/b.js"></script>
        <script src="/scripts/pag-a.js"></script>
        <script src="/scripts/pag-b.js"></script>
        <script src="/scripts/lay-a.js"></script>
        <script src="/scripts/lay-b.js"></script>
        <script src="/scripts/skel-a.js"></script>
        <script src="/scripts/skel-b.js"></script>
    </head>
    <body>
        Start of skeleton
    <div>
        Start of layout
    <div>
        Start of pageLayout
<div>
    bah blah blah
</div>
        End of pageLayout
    </div>
        End of layout
    </div>
        End of skeleton
    </body>
</html>

Upvotes: 3

Related Questions