0

Being an EE novice, I'm struggling to understand Parameter and Dynamic Variables. Yes...I gone over the documentation..MANY times. I'm still fuzzy on it.

For example, if I want to make a webpage using these layout variables (correct me if I'm using the wrong terms please) it could look like this?

<!-- header data here, etc --->

{layout:navigation}

<!-- my channel tags, etc --->


{layout:footer }

how do I tell expression engine what my footer is. Do I simply build a template within a related-named template group? Why don't I simply do this

{layout='layouts/_generic_layout'}
<!-- header data here, etc --->

        {layout="generic/.navigation"}

        <!-- my channel tags, etc --->


        {layout="generic/.footer"}

What am I not understanding? Secondly (let me know if I have to make another question for this one), when you go to create your dynamic layout set tag as shown above, it could look something like this correct?

{layout:set name="navigation"}
<!-- navigation content here -->
{/layout:navigation}

Could you please provide an example with your responses. Thank you!

1 Answer 1

3

Layouts are a bit hard to get your brain around to begin with. There are two things you need to know, and I think you'll be on top of it.

Layout templates work by letting you drop the content from one template within another. The places that the content appears are defined by the position of the {layout:variable} tags that you put within the layout template.

At their simplest, if a regular template includes a {layout="some/path"} tag, when that template is fired within EE all the content generated by the template is inserted into the specified layout template - the content is inserted at the point indicated by the tag {layout:contents}.

In a way that's it for the basic use case.

There are two advanced features to consider also. First, you can break up the output of the calling template into smaller parts, so rather than having all the content dumped in to replace the {layout:contents} tag, you can separate out the content into smaller chunks. You do this by bracketing the content by a layout tag pair - for example:

{layout:set name="more_content"}
<!-- some content here -->
{/layout:set}

If you do this in the calling template, when you create your layout template, you can include the content captured between the pair of tags wherever you like simply by including the tag {layout:more_content}. You can (if you want) include duplicates of this tag - in which case you get the content twice in your final output etc.

The second advanced feature is that you can 'nest' layout templates. So one layout template can link to a second (and that can link to a third and so on). This lets you build up pages from reusable bits of layout. Crudely, the output of the first layout template is simply inserted into the layout template it calls in the same way that the is discussed above for the single use example. One thing to bear in mind if you are using this second advanced feature is that {layout:variable} elements, while they are being unpacked into a final template to send to a browser, behave like global variables - so once you have defined {layout:some_content} in one place, it is available to any other layout templates called within the chain - so you don't have to explicitly hand such values on between templates.

So to look at your initial example, that won't work because each template can include just one {layout='path/name'} tag - if you put in more than one EE won't know where to put the content output by the template. But you could achieve that effect by chaining the three templates together - (so first template calls layout "footer", footer calls layout "header" and header calls layout "main page"). But whether this is the best plan depends a lot on what else is happening in your design.

HTH

====

Here is a simple example to address your supplementary question.

Let's suppose you have some content in a channel called "pets". In a regular template you might construct something like this...

<!DOCTYPE html>
{exp:channel:entries channel="pets" dynamic="no" limit="1"}
<html>
<head>
    <title>Pets FTW</title>
</head>

<body>
    <h1>{title}</h1>
    <p class="lead">{summary}</p>
    <p>{body}</p>
<ul>
    {pet_data_grid}
    <li>{pet_data_grid:name} is a {pet_data_grid:type} and has {pet_data_grid:number_of_legs} legs</li>
    {/pet_data_grid}
</ul>
</body>
</html>
{/exp:channel:entries}

We could split this into two bits - a layout template and a data template, like this:

{layout='_layouts/mylayout'}
{exp:channel:entries channel="pets" dynamic="no" limit="1"}
    <h1>{title}</h1>
    <p class="lead">{summary}</p>
    <p>{body}</p>
<ul>
    {pet_data_grid}
    <li>{pet_data_grid:name} is a {pet_data_grid:type} and has {pet_data_grid:number_of_legs} legs</li>
    {/pet_data_grid}
</ul>
{/exp:channel:entries}

where layouts/mylayout looks like this:

<!DOCTYPE html>
<html>
<head>
    <title>Pets FTW</title>
</head>
<body>
    {layout:contents}
</body>
</html>

These would give the same output as the original template.

NB. It is important to note that the HTML mark-up in the data template is carried over along with everything else to the layout template...

But we can be more adventurous. Let's suppose we want to put the heading and summary into a sidebar. We could do this like this...

{exp:channel:entries channel="pets" dynamic="no" limit="1"}

{layout:set name="some_name" value="{title}"}
{layout:set name="another_name" value="{summary}"}

    <p>{body}</p>
<ul>
    {pet_data_grid}
    <li>{pet_data_grid:name} is a {pet_data_grid:type} and has {pet_data_grid:number_of_legs} legs</li>
    {/pet_data_grid}
</ul>
{/exp:channel:entries}

and the layout template becomes...

<!DOCTYPE html>
<html>
<head>
    <title>Pets FTW</title>
</head>
<body>
    <aside>
        <h1>{layout:some_name}</h1>
        <p>{layout:another_name}</p>
    </aside>
    {layout:contents}
</body>
</html>

Note that the stuff we've marked out using layout variable tags is removed from the {layout:contents} tag - but anything in our calling template that hasn't been tagged as a {layout:variable} gets shipped over in the {layout:contents} tag.

The natural end-point of this type of approach is to separate out the preparation of data to display in a template from the HTML to display it - you just populate all the layout:variables in one template and put them into an HTML layout in another (layout)template.

HTH

4
  • Gavin, if I could throw money at you I would! One more question, in the first example, how does the Expression Engine tag {layout:contents} know where to pull from? You said it's not global. I understand that. I understand how to tag out other content for the "general way" of templating: {layout:set name="navigation"} <!-- navigation content here --> {/layout:navigation} But how does expression engine know what and where I mean when I call it by using the generic tag {layout:contents} Do I need to make sure I put this tag within the same template group where the data's called?
    – Greg
    Nov 16, 2016 at 14:55
  • Hi Greg. I've extended the original answer - hopefully the extra bits answer your supplementary question. But if not, let me know what is not clear and I'll try to clarify... Nov 16, 2016 at 18:08
  • Wonderful! Thank you! Permit me, one more dumb question, (shouldn't need an example) your using dynamic content for a template variable, per documentation, shouldn't we need a template partial for that? Or is this a subjective area within the EE community? I'm NOT trying to be "smart" after you've single-handedly explained so MUCH, so WELL. Thank you!
    – Greg
    Nov 18, 2016 at 15:13
  • Hey Greg. I may have got wrong end of stick, but Template Partials (or Snippets as they used to be called I think) are for reusing bits of templates across many templates - so where you want to use the same code in several places, but only want to maintain it once. Layout variables are different in that they contain content (and possibly some layout). So use cases are different - but there is a big overlap between them. HTH. Nov 19, 2016 at 1:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.