Problems, need help? Have a tip or advice? Post it here.
3 posts Page 1 of 1
I just stumbled upon the concept of buffering output using the capture tag (http://www.couchcms.com/docs/tags-refer ... pture.html) in the contact form tutorial.

If I understand this correctly, we store the content within the capture tags in a variable which we then echo to the view:

Code: Select all
<cms:capture into='my_variable' scope='global'>
    ..everything executed here will get stored in variable 'my_variable' at the requested scope.. 
</cms:capture>

</cms:show my_variable />


The question is why would we do that?

The only logical use case I see (in the context of the contact form tutorial) is that we want to make a local variable from a specific template available in the global context; e.g. show social media links at another place without creating a new variable in another view (footer, header etc):


Code: Select all
<cms:set has_profile='1' 'global' />

<cms:if has_profile >
     <cms:show profiles_output />
</cms:if>



- Is this the intended use case of the capture tag?
- Is it safe to set global variables in this way?
- What is the recommended way to work with variables that should appear at a global context (e.g. contact information, social media links etc)?

I would appreciate your clarification.
Hi,

I'll attempt to explain.

You are right in that cms:capture stores the results of the code enclosed within it in a variable.
We can show the variable further on anywhere in the page flow - perhaps immediately after the cms:capture block.

The important point above is not that we saved the value in a variable. Important point is that we executed some code but did not display its output immediately. If so we choose, we can ignore that output completely or check some condition further on and then show it.

I.e. it makes it possible to control programatically whether or not to show output of some piece of code depending on conditions that come after that code in the page flow.

The statement hilighted above is the crux of the matter.

Let us illustrate it with the following example -
Code: Select all
<div class="soc-icons"><span>Find Us:</span>
    <cms:if twitter_id>
       <a href="<cms:show twitter_id />"><img src="images/icon-1.jpg" alt="Twitter"></a>
    </cms:if>
    <cms:if facebook_id>
       <a href="<cms:show facebook_id />"><img src="images/icon-2.jpg" alt="Facebook"></a>
    </cms:if>
</div>

As you can see, in the code above we check if a social account is set in the admin-panel and then display its icon. So, e.g. if only twitter was set the final output would be -
Code: Select all
<div class="soc-icons"><span>Find Us:</span>
   <a href="@something"><img src="images/icon-1.jpg" alt="Twitter"></a>
</div>

What happens if none of the social accounts were set? We'll get this -
Code: Select all
<div class="soc-icons"><span>Find Us:</span>

</div>

Do you see the problem? We are outputting the "Find Us" div even when there are no social accounts to show. That is happening because the conditions that have a bearing on it come after it.

One way of handling it would be to check the accounts before outputting 'Find us' -
Code: Select all
<cms:if twitter_id || facebook_id>
    <div class="soc-icons"><span>Find Us:</span>
    <cms:if twitter_id>
       <a href="<cms:show twitter_id />"><img src="images/icon-1.jpg" alt="Twitter"></a>
    </cms:if>
    <cms:if facebook_id>
       <a href="<cms:show facebook_id />"><img src="images/icon-2.jpg" alt="Facebook"></a>
    </cms:if>
    </div>
</cms:if>

The example above is simple. For complex enclosed code things can get difficult to check beforehand.

For such cases, we defer the output of the code, go along the flow as usual and the set a signal from within if all conditions are met for display. This we do using cms:capture -
Code: Select all
<!-- execute code but do not display anything -->
<cms:capture into='profiles_output' >
    <div class="soc-icons"><span>Find Us:</span>
    <cms:if twitter_id>
       <a href="<cms:show twitter_id />"><img src="images/icon-1.jpg" alt="Twitter"></a>
       <cms:set has_profile='1' 'global' />
    </cms:if>
    <cms:if facebook_id>
       <a href="<cms:show facebook_id />"><img src="images/icon-2.jpg" alt="Facebook"></a>
       <cms:set has_profile='1' 'global' />
    </cms:if>
    </div>
</cms:capture>

<!-- display if all conditions met -->
<cms:if has_profile >
    <cms:show profiles_output />
</cms:if>

If you are interested in more concrete examples, please see the following threads -
viewtopic.php?p=9634#p9634
viewtopic.php?p=13138#p13138

Replying to your other queries -
- Is it safe to set global variables in this way?
It'd be 'unsafe' if your variables could overwrite some system variables. As you know, all system variables in Couch are prefixed with a 'k_' and are not allowed to be changed using cms:set. So, this problem never arises.

What is the recommended way to work with variables that should appear at a global context (e.g. contact information, social media links etc)?
It is explained in detail at http://www.couchcms.com/docs/tutorials/ ... -ends.html. I can only suggest that you name the variables with something identifiably yours like prefixing with a 'my_ or 'g_' (for global).

Hope this answers your query.
@KK thanks for the detailed answer. That makes perfect sense... :)
3 posts Page 1 of 1