I am designing the opening page of my personal web site. I am trying to use the same service function as the 'blog' section opening which retrieves the latest blog entry.
However I only want up to the 2nd paragraph to display on the opening page of my person web site. For me to re-use the service function I would need to parse after the second
</p>
within Twig. In other words I would want something like
<p>blah1 blah1 blah1</p>
<p>blah2 blah2 blah2</p>
to be the result. What syntax is needed in Twig?
You could do something like this...
Let's say that your text content is inside a twig variable named content.
Split your text content on every occurrence of </p>:
{% set contentArray = content|split('</p>') %}
First paragraph is everything inside first element of array after the first occurrence of <p>
{% set firstParagraphArray = contentArray[0]|split('<p>') %}
{% set firstParagraph = '<p>' ~ firstParagraphArray[1] ~ '</p>' %}
Second paragraph:
{% set secondParagraph = contentArray[1] ~ '</p>' %}
Output:
{% autoescape %}
{{ (firstParagraph ~ secondParagraph)|raw }}
{% endautoescape %}
Alternatively, you could make twig extension, that does all this job, and makes twig code a little bit cleaner.
Related
Good morning,
Im trying to build a component where the data arrives in json form from a cms. I need to be able to use an object from the array as the file to include in the twig template. Something like this..
{%cards [{component: '#-card', cardOptions: {''}}, {component: '#-card_small', cardOptions: {''}}] %}
{% for card in cards %} {% include card.component with card.cardOptions only %} {% endfor %}
The problem I have it doesn't seem to parse the '#' from the json and I get the error "file.indexOf is not a function". The project is set up to use '#' as the prefix so I have no way to change that. Iv tried to concatenate in various ways but nothing works. Without the '#' symbol it parses as I expected.
Thank you for any help.
Thanks to your replace suggestion DarkBee, I fixed it by using
{% for card in cards %}
{% set card = '#' ~ card.component %}
{% include card with {card.cardOptions, card:card} only %}
{% endfor %}
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 )
I have picked up the basics of using TWIG to create my site. I suppose I know how to use {%extend%} {%block%} {%include%} and {%set%}, in the most general sense.
I would like to include a block of code from within another twig file without including the whole file - as opposed to {% include 'file.twig' %}.
I have figured out how to set a variable in file.twig and output it using {{ variable | raw }}. I would like to do that in another file, like you would with using jQuery's .load function.
I swear the twig documentation does not seem to touch on this, it seems like really obvious and basic functionality. I have messed around with various combinations of include, for, with, in and only, colons and commas and whatever | is, and nothing.
I believe you are looking for horizontal inheritance via the use tag:
The use statement tells Twig to import the blocks defined in blocks.html into the current template (it's like macros, but for blocks)
The confusing part is that by itself, {% use ... won't actually insert the content of the blocks in the referenced template. To do that, you must use the block(...) function:
index.twig
{% use "blocks.twig" %}
{{ block('name') }}
blocks.twig
{% block name %}
<h1>Alex Weissman</h1>
{% endblock %}
{% block hobby %}
<p>Blanchin'</p>
{% endblock %}
For a working example, see my TwigFiddle (yes, it's a real thing!): http://twigfiddle.com/jjbfug
Currently I am working on a controller class which should be able to let a customer add an item to a table in a database and view these items (e.g. a movie).
I am using the following twig code:
{% extends 'base.html.twig' %}
{% block body %}
{% if movies|length == 0 %}
There are no movie items available. Add a movie here to get started.
{% elseif movies|length != 0 %}
These are the results: ...
{% endif %}
{% endblock %}
What is the best way to let a user/customer or whatever the case, add an item to the table that needs to be shown? Should I let a user fill a form on the exact same page as the overview template (I personally do not think this is good, as I want to keep purpose of each page seperated) or should I make a different template with a form where the user will be send to (though this takes redirection time, which some users might be getting annoyed by)? As you can see I am using an anchor tag on the word "here". How should I set-up the anchor tag if I am to use a different template for creating records in a table?
As the documentation of Symfony shows the following:
Home
The path says _welcome and I think it refers to the name of the route that points to a certain controller. Would it be best to use this path function and what would I need to add where it now says _welcome (or was I correct one sentence ago)? And why is there an underscore in the given example?
I am asking this question because when I worked with ASP.NET MVC, there was this method called ActionLink() and made me wonder if this is most common use of redirecting, since you could also just add the template file location to the anchor tag href attribute?
If the form to add a new item is small (one text field + one submit button), you could add the form in the same page.
For example :
{% extends 'base.html.twig' %}
{% block body %}
// display your form here
{% if movies|length == 0 %}
There are no movie items available.
{% elseif movies|length != 0 %}
These are the results: ...
{% endif %}
{% endblock %}
But actually it's up to you to decide if you want it to be displayed in the same page or not.
In the case you decide to redirect the user to a new template, especially for the form, you write the name of the route of the correspondant controller :
here
So the code of the controller will be executed and will redirect to the page of your form.
Concerning "_welcome", I don't know why they write it like this. This is more the way to name a layout file than a route name.
I want to achieve the following thing:
I have a basic template for all of my pages, named "_page_base.twig". It contains the header and footer.
Then I have a Template for different areas of the page: "topic.twig", "section.twig" and "article.twig" - each of them extending the "_page_base.twig", thats working well so far.
Now I want to write my articles. I would love to save them as .twig file as well, since I can edit the complete markup in my editor and just upload it.
Since I can't say that my article files just extend "article.twig" (multiple inheritance is not possible) I could tell the "article.twig" that it should use blocks from my different article-content twigfiles.
The problem is: "use" statements have to be hardcoded!
My current solution is to add {% use "[PLACEHOLDER]" %} into the "article.twig" and then loading the template into a string, replacing the placeholder to the correct article-content.twig and then passing the whole thing to the template engine. What a mess.
Have you guys any idea for a better solution?
You can try with include tag. Since this tag accepts a dynamic name template to include, you just only need to define a variable which contains the name of article twig template.
{# on article.twig#}
{% set articles = ['someArticle.twig', ...] %}
{% for article in articles %}
{% include article %}
{% endfor %}
{# on someArticle.twig #}
... Article text ...
In the case of you need to customize some content inside of someArticle.twig you could stage the next level: embed tag. You should define a block tag inside of someArticle.twig, this block will be the placeholder to the custom values.
{# on article.twig#}
{% set articles=['someArticle.twig', ...] %}
{% for article in articles %}
{% embed article %}
{% block inside_text_article %}
... custom text ...
{% endblock %}
{% endembed %}
{% endfor %}
{# on someArticle.twig #}
... article text ...
{% block inside_text_article %}default values{% endblock %}
... article text ...
https://github.com/fabpot/Twig/issues/17 - no dynamic namespaces
LiipThemeBundle might be a solution:
http://symfony2bundles.org/liip/LiipThemeBundle
Unless I am not understanding the question, displaying a single article only requires that it also extends __page_base.twig.
In the case that you would need to display multiple articles, you could have a template dedicated to showing a list of articles which would also extend __page_base.twig and pass the article list to this template.