How to include twig file from array? - php

Hi how do I pass a array to a twig include?
{% set navbar_logo %}["{{sprinkle|raw}}/components/content/navbar/navbar-logo.html.twig", "/components/content/navbar/navbar-logo.html.twig"]{% endset %}
{% include navbar_logo %}
this results in:
Unable to find template "["#admin/components/content/navbar/navbar-logo.html.twig", "/components/content/navbar/navbar-logo.html.twig"]"
this works fine:
{% include ["{{sprinkle|raw}}/components/content/navbar/navbar-logo.html.twig", "/components/content/navbar/navbar-logo.html.twig"] %}
But i need to get it from the variable.
This also works:
{% set navbar_logo %}{{sprinkle|raw}}/components/content/navbar/navbar-logo.html.twig{% endset %}
{% include navbar_logo %}
But I need the backup incase the first one does not exist.
How can I do this?

What about:
{% set navbar_logo = include(sprinkle|raw ~ '/components/content/navbar/navbar-logo.html.twig') %}
I don't exactly know what you're trying to achieve, but a better approach would be to set this in a block of your base layout.
{% block navbar_logo %}
{{ include(sprinkle|raw ~ '/components/content/navbar/navbar-logo.html.twig') }}
{% endblock %}
Then when you later need to dump your logo, use {{ block('navbar_logo') }}.
More about blocks

If you're using {% set .. %}... {% endset %}, Twig is treating the variable as a string
You should switch your code to this and then it works
{% set navbar_logo = [ sprinkle~"/components/content/navbar/navbar-logo.html.twig", "/components/content/navbar/navbar-logo.html.twig"] %}

Related

Concatenate output from template file inside twig for loop to variable?

I have a situation where I need to include a template file inside another template and output it in a for loop. The problem I am having though, is that it's outputting to a container and I only need the container to render once, but I need the included template to render on all iterations of the loop.
{% for details in array %}
{% set data_details %}
{{ include('data.html.twig') }}
{% endset %}
<!-- Other HTML needed in the loop -->
{% if loop.first %}
<tr class="table-row">
<td>
{{ data_details | raw }}
</td>
</tr>
{% endif %}
{% endfor %}
As you can see, the {% if loop.first %} prevents the container from repeating. But I need data.html.twig to loop on every iteration and append the HTML to the data_details variable but the variable only contains the last iteration. I am not that knowledgeable with Twig so maybe I am going about this the wrong way. The documentation says if you wrap something in a set it will "capture" the output but that isn't happening for some reason.
You're close, the iteration does overwrite the already set variable.
To append to the already set variable , you can repeat/output the variable in the wrap to recapture/concatenate it
{% set data_details %}
{{ data_details | default('') }}
{{ include('data.html.twig') }}
{% endset %}

How to render Twig / PHP / HTML template blocks as an arbitrary array of exploded subsections?

I've been beating my head against this for a while, because while it's "easy" to do in raw PHP, the result is not extendable due to PHP's lack of decent built-in templating syntax. So I installed Twig assuming it would have a built-in explode function for iterating amongst blocks. But there seems to be no way of dividing content into an arbitrary number of subsections.
I considered using {% embed %}, but the document is to be styled according to which sections appear in the parent template. And in what order (which is variable; this is for a form with a lot of business logic in it.)
I've built the form in PHP and gotten it to work as a "very pretty" static page with easily an arbitrary number of subsections, all working and interactive regardless of which are displayed (based on e.g. user privileges), but templatizing it is the challenge.
The static (twigless) version relies on me exporting the parsed content to an array which can then be wrapped with the appropriately-styled div's for each visible section. This works, but requires me to use included html and object buffering which looks awful and would not be easy to maintain:
$content = include("form_content_html.php"); // return an object-buffered array
// I was including the escaped values here using if isset($data) and echo short tags.
foreach ($content as $section) { /* do something; */ }
$template = include("form_template_subsection.php");
$formview->addSubsectionTemplate($template);
echo $formview->addSubsection($content,$i++,$type);
// fill section of $type with $content[$i] if isset
echo $formview->addSubsection($content,$i++,$sometype);
// $types have different css class for certain effects
// etc. not the best approach.
(I need to escape all user / db content before binding it to the form values, but since the form fields are highly customized I separated them into their own content layer so that's the only layer that has content that needs to be escaped at present.)
So forget that, now I'm using Twig. (note: not Symfony2, as the project is on a shared webhost.)
I don't think there's a way of {%extend%}ing the parent template such that some of the child template blocks are "dropped into" the named parent template containers, with the rest ignored; which is what I'm looking for since that way I can put all the logic into the top level (which sections of the form to make visible, etc.) and pass in the values first.
Note that the style of the form sections is dictated by the structure of the parent template, not by the child content. E.g. section 1 may display content 1 and call css on content 2 in section 2; or section 1 and 2 with the same css may display different content.
If I split up the form into 15 content-only subtemplates, and then conditionally included them in the parent file, it would work. But that would seem to defeat the purpose of using a template engine? Although I suppose Twig makes it much easier to work with included files containing html snippets in this way, so let me know if that is a preferred solution.
Should I divide the content node up into numbered {% block1 %}, {% block2 %} etc. subsections and then renderBlock in my PHP view class?
If Twig had a {% section %}...{% section %} syntax allowing you to split up the template into chunks and then parse each chunk as an array of block elements... well, I half-expected that, and wish I could add one myself.
Is this a possible solution? From the Twig documentation:
Horizontal reuse is a way to achieve the same goal as multiple
inheritance, but without the associated complexity:
{% extends "base.html" %}
{% use "blocks.html" %}
{% block title %}{% endblock %}
{% block content %}{% endblock %}
The use statement tells Twig to import the blocks defined in
blocks.html into the current template (it's like macros, but for
blocks):
{# blocks.html #}
{% block sidebar %}{% endblock %}
Note: The use tag only imports a template if it does not
extend another template, if it does not define macros, and if the body
is empty. But it can use other templates.
Well, that's a bit thoroughly less than unclear.
(Does "it" refer to the imported template being able to use other templates, or does "it" mean a template can use more than one template, or both? and if the body is empty, does that mean the body of the imported block tag? If so then perhaps it is not a solution.)
Would it be possible to do something like this:
{# form_template.html #}
{% extends "form_content.html" %}
{% block section1 %}
<div class="{{ style1 }}"><div class="{{ style2 }}">etc.
{{ parent() }}
</div></div>{% endblock %}
Or this?
...
{# form.html #}
{% use "form_content.html" %}
{% for sections as i %}
{% block wrapper_elements %}{% block section{{i.name}} %}{% endblock %}
{% endblock %}
{% endfor %}
{# form_content.html #}
{% use "form_fields.html" %}
{% block section1 %}{% if field1 %}
Actual content here: {% block field1 %}{% endblock %} And here
{% else %} {% endif %}
{% endblock %}
{% block section2 %}More actual content here{% block section2 %}
But if so, how to iterate over the sections prior to calling each one in form.html?
I've found the solution, I think:
(From the Twig documentation)
The set tag can also be used to 'capture' chunks of text:
{% set foo %}
<div id="pagination">
...
</div>
{% endset %}
Ergo, set can be used to iterate over anonymous consecutive blocks:
{% set i=0, out=[] %}{# declare top scope #}
{% block initialize_content %}{# use once #}
{% set i=0, out=[] %}{# prevent dupes #}
{% set foo %}
<div id="pagination">...</div>
{% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %}
{{ escape_variables_here }} ... more html
{% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %}
{{ variables_all_scoped_to_same_context }} ... more html
{# so dividers can be moved "up and down" if necessary ... #}
{% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %}
{# ... like this. ^^a tag/macro could probably define this #}
{% endset %}{% set out=out|merge({ i: foo}) %}
{# or loop over i = 0..n or i = loop.index0 #}
{% endblock initialize_content %} {# end setter #}
{% block content %}
{% if key is defined and out.key is defined %}{{ out.key |raw }}{% endif %}
{# output top-scoped var (outputs nothing if setter not called) #}
{# the setter doesn't have to be in its own block, but that allows
the variables in the content to be redefined in setter's scope. #}
{% endblock %}
(cf. Setting element of array from Twig )

symfony2 - how to include a twig from a twig

Learning sympony2 and I have hit a wall and have tried numerous solution but nothing seems to work, I keep getting the
Unable to find template "ScoreBoardViewerBundle.Viewer.scoreboard_keeper.html.twig" in
ScoreBoardViewerBundle:Viewer:view.html.twig at line 15.
Here is my twig snipped:
{% if score_keeper=='sk' %}
{% include 'ScoreBoardViewerBundle.Viewer.scoreboard_keeper.html.twig' with {'score_keeper' : score_keeper} %}
{% else %}
{% include 'ScoreBoardViewerBundle.Viewer.scoreboard.html.twig' %}
{% endif %}
Initially I had only the file name, like I seen on examples from this twig site: Twig site but that produced the same error. The twig files are found in the same directory.
What am I doing wrong? Also I get the same issue regardless which file I try to include. I did have some typos but they should be fixed.
Here is the Controller I was using and it was able to open both views correctly, I just noted some twig in each file was redundant so hence the changes
public function viewAction($score_keeper)
{
//returns scoreboard view for score keeper
// if($score_keeper=="sk"){
// return $this->render('ScoreBoardViewerBundle:Viewer:keeper.html.twig',array('score_keeper' => $score_keeper));
// }
//returns scorboard view for all others
return $this->render('ScoreBoardViewerBundle:Viewer:view.html.twig',array('score_keeper' => $score_keeper));
}
You have a typo in your {% include %} statements. You are supposed to use : instead of . to separate blocks in template name.
Try this:
{% if score_keeper=='sk' %}
{% include 'ScoreBoardViewerBundle:Viewer:scoreboard_keeper.html.twig' with {'score_keeper' : score_keeper} %}
{% else %}
{% include 'ScoreBoardViewerBundle:Viewer:scoreboard.html.twig' %}
{% endif %}

What is the html template use by symfony for file type field?

I try to customize the file field in my form. Just as I do for other fields.
I simply overrid some parts of the html template (whatever it is, textarea for instance, or choice) ==> here the list of html template that make up any field Github
The fact is I cannot find the file template in the link. (in the documentation it is said to give all template for any field)
Any idea about how to customize the file widget?
HERE A DESCRIPTION OF WHAT I WOULD LIKE TO ACHIEVE:
I want the change the way is deplayed the html part which display the name of the file that has been chosen by the user.
Moreover, I am open about any find of suggestion about any methotology about how to customize this file widget. might be some other way of doing it... let me know please.
As file input is just a simple <input type="file"> it is rendered in {% block form_widget_simple -%} which you can easily find in form_div_layout.
If you want to change the view of this element you can change a bit form_widget_simple (from bootstrap_3_layout):
{% block form_widget_simple -%}
{% if type is not defined or 'file' != type %}
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %}
{% endif %}
{{- parent() -}}
{%- endblock form_widget_simple %}
Or by creating custom block, as its described here:
{% block file_row -%}
{# file row template #}
{% endblock file_row -%}
Or if you want to customize only the widget
{% block file_widget -%}
{# file widget template #}
{% endblock file_widget -%}

Twig filter included template

I wanted to do something like this:
{{ include("tpl.html")|f }}
But that doesn't seem to work, it just printed tpl.html without any filtering, then I tried:
{% filter f %}
{% include "tpl.html" %}
{% endfilter %}
And it worked. I just wonder, why can't I use shorter one? Do I misunderstand something?
Thanks in advance.
Sorry for being that long to come back :-)
The fact is that the include function writes on the template.
If you do :
{% set s = include('FuzHomeBundle:Default:test.html.twig') %}
Which is not supposed to display something, you'll get the content of the file output anyway, and the s variable will be set to null.
If you do instead :
{% filter upper %}
{% include 'FuzHomeBundle:Default:test.html.twig' %}
{% endfilter %}
or
{% filter upper %}
{{ include('FuzHomeBundle:Default:test.html.twig' }}
{% endfilter %}
The filter tag will compile some code that control output buffer.
To apply a filter on a section of code, you have to wrap it with the filter tag:
{% filter f %}
...
{% endfilter %}
What you were trying originally is to filter a variable which in twig is defined by the double parenthesis:
{{ variable name|filter }}
to read more check out the twig documentation on filters here

Categories