I have a nested layout setup (page has a layout, and that layout has a layout), like so:
{!-- site/page.html --}
{layout="site/_page_layout"}
I'm page contents!
{!-- site/_page_layout.html --}
{layout="site/_layout"}
{if layout:contents}
Page says {layout:contents}
{if:else}
Silence is golden.
{/if}
{!-- site/_layout.html --}
{layout:contents}As above, the {if layout:contents} evaluates to false (which it shouldn’t).
What’s more, if I explicitly set the Page’s content to “contents”, then the entire conditional is seemingly ignored, and the final output is simply “I’m page contents!”, e.g.:
{!-- site/page.html --}
{layout="site/_page_layout"}
{layout:set name="contents"}
I'm page contents!
{/layout:set}Everything works as expected if I explicitly set my page’s partial content to a different variable name, e.g.:
{!-- site/page.html --}
{layout="site/_page_layout"}
{layout:set name="page_contents"}
I'm page contents!
{/layout:set}Then the conditional (obviously changed to use new variable name) works OK.
Cheers, John
That’s gotten me halfway there - now when layout:contents is implicitly set, things work fine. But if I explicitly set layout:contents in my parent template, it still ends up being the same layout:contents output in the layout’s layout (head hurts).
The explicit/implicit thing I only say because I tested that it worked in 2.8, and presented it as an allowable thing at the GeeUp conference - to me it seems worthwhile to allow people to explicitly set layout:contents, not just for those who prefer to have clear code, but also to give people options in how they conditionally set the value.
Does that make sense?
It does make sense, and unfortunately we did note in the user guide “The name contents is reserved for the template data.” Starting with 2.9 we will be strictly enforcing that with an error if the template parser encounters a layout tag attempting to set a variable named “contents”. That’s the bad news. The good news is simply changing the variable name (e.g. “my_contents”), and opting never to use {layout:contents} in a template should restore your desired functionality.
What’s the thinking behind that enforcement? Walking through the behaviour with 2.8 it seemed to make sense to me - I also mentioned it as an option at the GeeUp conference, that you could choose to explicitly set layout:contents if for some reason you wanted to (clarity if nothing more).
What’s the thinking behind that enforcement?
Given this template:
{layout="site/.layout" contents="Uh-oh"}
Hello world!And this layout:
<html>
<body>
{layout:contents}
</body>
</html>What should the output be? If we choose to use “Uh-oh” then how does the template writer gain access to “Hello world!”. The same is true vice versa. And if we were to append one to the other which takes precendence? So we have a problem of ambiguity. This is why we initially reserved “contents”, however we neglected to enforce that in code the first time around and only noted it in our user guide.
The functionality doesn’t change with this either, as you can still get the same thing using a non-reserved word. I certainly appreciate how getting used to doing it a certain way with an add-on can develop some brain muscle memory, but it was only that way because that’s how a module has to do it. This is built into the template engine, so the more intuitive approach is for the template to simply be the content, as it is in all other cases outside a layout context. And as with other system variables, it should not require reverse engineering a site developer’s installation to determine where it’s coming from.
There is already a cascade of what set approach “wins” (parameter vs dynamic), and it at least made sense to me that an explicit set of “contents” won out over an implicit set.
I suppose it’s not the end of the world because if people prefer explicit setting, they can do so just with other variable names.
FWIW I might have considered designing it so that once you specified a layout for a parent template, then none of the parent template’s content was output if not explicitly captured in a variable, and then doing away with the entire default “contents” concept - it would be simply that if you want to use the layout, then you must set some variables for it. But I can appreciate that the underlying template engine has certain ways it must do things…
Interesting that you’re considering append/prepend capabilities, I think the community would definitely welcome this at some point. The obvious way would be to introduce parameters append="yes" or prepend="yes", and I don’t think this would at all need to alter the aforementioned parameter vs dynamic cascade (dynamic will always overwrite parameter, even if dynamic is in a loop and is set to append/prepend). I mean I guess you could if you wanted to also have a append_default=”yes” or prepend_default=”yes” if you really wanted to cover your options, but that seems overthinking it (be warned: I tend to do that a lot).
I’d also still like to see a more graceful way of establishing default layout variable content when nothing has been set by the parent template (http://ellislab.com/forums/viewthread/243211/). But here I go way off topic…
Thanks! John
But I can appreciate that the underlying template engine has certain ways it must do things…
To be clear, this is choice, intent, not some artifact that we are simply choosing to live with.
I’d also still like to see a more graceful way of establishing default layout variable content when nothing has been set by the parent template (http://ellislab.com/forums/viewthread/243211/). But here I go way off topic…
Fallbacks would be great, in fact it would be nice for all variables that are set within templates to have fallbacks (embed vars come to mind.)
Packet Tide owns and develops ExpressionEngine. © Packet Tide, All Rights Reserved.