Take the 2-minute tour ×
Craft CMS Stack Exchange is a question and answer site for administrators, end users, developers and designers for Craft CMS. It's 100% free, no registration required.

I have a main layout file and extending it with another template. I have my markup and content in the {% block content %}{% endblock %} however, I'd like to add content to another "block" on the individual entry page for meta data - that would require adding another {% block content %} to my template as it would need to be output in a different area of the layout template.

Essentially, is there a way to add a second block (perhaps name it differently) or is my best bet to set all that meta data as a variable and pass it that way?

share|improve this question

2 Answers 2

up vote 7 down vote accepted

Option A: Set individual properties in the child template

If you want to set specific meta properties instead of defining a block, you can include lines like this in _layout.html:

{% if metaDescription is defined %}<meta property="description" content="{{ metaDescription }}">{% endif %}
{% if metaKeywords is defined %}<meta property="keywords" content="{{ metaKeywords }}">{% endif %}

Then, you can simply set either value from within the child template...

{% set metaDescription = entry.summaryFieldOrWhatever %}
{% set metaKeywords = entry.tagField %}

Option B: Pack an array with properties in the child template

...or as you pointed out, that could get cumbersome if you have a whole bunch of meta data. In that case, you could take a similar approach with an object instead of a block. So in _layout.html:

{% if metaProperties is defined %}
     {% for prop in metaProperties %}
     <meta property="{{ prop.name }}" content="{{ prop.value }}">
     {$ endfor %}
{% endif %}

In the child template, then, you could...

{% set metaProperties = [
    { name: "description", value: entry.summaryFieldorWhatever },
    { name: "keywords", value: entry.tagField }
] %}

This way, you could set as many items as you'd like and still avoid passing markup to the parent template.

share|improve this answer
    
This is great for simple strings, but when it's 10 lines of open graph code, I thought a block was better suited. –  Ryan Shrum Jul 9 at 16:25
    
@RyanShrum It very well may be, but you can also pass objects too! I'll update my answer since it'd make an awful comment. –  Matt Stein Jul 9 at 16:28
    
Would love if someone could weigh in here on best practice with specific regard to performance. I love the idea of passing an object. Are there any performance hits using the block method? –  Ryan Shrum Jul 9 at 17:28
    
@Ryan I wouldn't be concerned about performance, with either method. Which method do you prefer in other respects? I'd say the Block method is easier to maintain (readability) as you have html and values side by side. Using an Object lets you call your variable values in the complete parent template, you don't need to inject your meta data html as one single block. –  carlcs Jul 9 at 19:47
    
@RyanShrum My guess is that the performance difference would be negligible, but my guess is about as authoritative as math tips from a houseplant. –  Matt Stein Jul 9 at 19:48

In my example ({% block content %}), the variable is "content" so you can create additional blocks by naming the block something different and outputting it in your layout template - reference Twig docs for more examples.

By adding a new block {% block meta %} I was able to output entry specific meta data.

Example:

Child template: group/template.html

{% extends "_layout" %}

{% block meta %}
<meta property="og:title" content="{{ entry.title }}">
<meta property="og:site_name" content="{{ siteName }}">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US"> 
<meta property="og:url" content="{{ entry.url }}">
<meta property="og:description" content="{{ entry.body|hacksaw(chars=300) }}">
<meta property="article:published_time" content="{{ entry.postDate|date('U') }}">   
{% endblock %}

{% block content %}
...
{% endblock %}

Parent template: _layout.html

<!DOCTYPE html>
<html>
<head>
    {% block meta %}{% endblock %}
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>
share|improve this answer
    
Also, check out the Twig parent() function: twig.sensiolabs.org/doc/functions/parent.html –  Andrea DeMers Jul 9 at 16:46
    
Are you really using the embed tag? Not just a simple extends '_layout' with parent()? –  carlcs Jul 9 at 19:57
    
I updated my answer with both templates' code, in the simplest sense. I could be wrong, but I don't think parent() applies here as I'm not trying to append anything to the parent. I think using the object method mentioned in the other answer might be better. Iterating through that and only having one line of markup in the parent template (layout) sounds better to me. –  Ryan Shrum Jul 9 at 20:19
    
@RyanShrum I think Christian meant that you could have a {% block head %} inside the <head> element that includes the page title, stylesheet references, etc. and then easily append more meta properties (or any valid <head> markup) as needed. I've done this as well, I'm just a fan of the object syntax for whatever reason. –  Matt Stein Jul 9 at 21:25
    
@Ryan, sure you don't need to use parent() but it is an elegant way to leave shared meta or other head tags in _layout and include / override it dynamically. –  carlcs Jul 9 at 21:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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