Every page can be served in two ways - an "html" and a "json" way.
The "html way" contains a full fledged html page - header/footer/menu/main content - just like every page.
The "json way" contains only the page-specific things, like the content and the title.
To achieve this, in every template I extend from base.html.twig that contains the following lines:
{% extends app.request.isXmlHttpRequest()
? "base/ajax.json.twig"
: "base/full.html.twig" %}
full.html.twig is just a file that wraps the content within header/footer/menu.
ajax.json.twig contains this:
{
"title": "{% block title %}{% endblock %}",
"content": "{% block body %}{% endblock %}"
}
The idea with all this stuff is to easily create flexible pages that can be served both as html page and an json reponse depending on app.request.isXmlHttpRequest()
The problem is that in base/ajax.json.twig I have to escape the content in the body block so that the file is a valid json object, e.g. <a href="/"> makes it invalid json because the quotes are not escaped:
{ "content": "<a href="/">" }
I need something like {{ parent()|json_encode() }}, not with parent() but with child(), that unfortunately I couldn't find in the docs.
Any suggestions?
You can call block as function from layout. In your case layout will look so:
{% set tmp = {title:block('title'), content:block('body')} %}
{{ tmp|json_encode }}
Related
layout.twig
<main class="main">
{% block content %}{% endblock content %}
</main>
{% block footer %}{% endblock %}
page.twig
{% extends 'layout.twig' %}
{% block content %}
{#abc#}
{% block footer %}
{#123#}
{% endblock footer %}
{% endblock content %}
When I do this. Footer block renders twice. Once after content block and once the place it should be
NOTE: I simplifed the templates to make them more readable. The problem I see is I cannot use block inside another block. if I use it renders twice.
I have to use footer inside block content. I don't want to include extends and content in every page. Because it is same. I use something like below.
$tm['p'] = "{% extends '" . $layout . "' %}{% block content %}";
$tm['p'] .= $page;
$tm['p'] .= "{% endblock content %}";
$load = new \Twig_Loader_Array($tm);
$tw = new \Twig_Environment($load);
print $tw->render("p", $dat);
I think it's because you're nesting a previously define block insinde another previously defined one when overriding one. A block is usually used to define placement for output elements, so it's kind of wrong that you're placing footer inside content and where it should be actually means after content block, where you defined it in layout.twig, that's the right place according to your template files. If you need to override footer, you should simply do this outside of content block inpage.twig like this:.
{% extends 'layout.twig' %}
{% block footer %}
{#123#}
{% endblock footer %}
{% block content %}
{#abc#}
{% endblock content %}
Please note, the order of overridden blocks in page.twig is not important because you already made the decision about this in layout.twig.
Looking at your example, I think you want to place footer inside <main></main> not the content block. If so, you might need to modify layout.twig. Some changes like the following:
layout.twig
<main class="main">
{% block content %}{% endblock content %}
{% block footer %}{% endblock footer %}
</main>
Templates are useful when you want to design page layout and elements' placements, and later only change their content not their placements. So you should design your layout.twig according to your needs, and if you need an alternate layout, feel free to create an additional one. For example if you need two layouts, one with footer inside the content and one with footer outside the content.
And about not repeating extends and blocks (content as you pointed) in every page: In my opinion it is not a good idea to remove the extends tag from top of the page. It is good for reference, to know which page template is extending which layout. And what you are doing is writing template source code as PHP strings. This is not a good practice. I suggest you consider saving your templates in separate files like you did with layout.twig and page.twig and put all fixed content inside them. And if you find yourself repeating some code very often, then you might want to rethink about your templates structure because on of the main advantages of templates hierarchy is to avoid writing common code by reusing it.
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.
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.
This question already has answers here:
How to create a template in HTML?
(3 answers)
Closed 9 years ago.
I have worked on several ASP.NET applications recentely, and I was simply fascinated by the simplicity of it's HTML layouting.
Basiccaly there is one layout file, in which you write all the static HTML, CSS, JS, or really anything that will stay the same on all pages. Then, there are content pages, in which you only write the content of the pages.
So, for example you have an about.cshtml file that looks like this:
<h1>My name</h1>
<p>I am a junior web developer... etc</p>
<p>Contact me at example#gmail.com</p>
That's all the information needed for the about content page, when requested it will be inserted in the layout page.
So, my question:
Are there any ready-to-use tools to make this happen via html, javascript or php? I found myself implementing it via ajax calls, but that really is just a waste of resources, having to async load all the html files I have.
For pure HTML, you could go down the route of using a static site generator. For example:
Jekyll
Pelican
In Pelican you have a base.html template, which contains everything that you want to appear on all pages, so the header and footer etc (These can also be called .header.html and then referenced in the main.html template.
Page content is written in Markdown, and put into folders called posts or pages, and then you run a generate command, and it will output all the html for you.
And pages can be written like this:
{% extends "base.html" %}
{% block title %}{{ page.title }}{%endblock%}
{% block content %}
<h1>{{ page.title }}</h1>
{% import 'translations.html' as translations with context %}
{{ translations.translations_for(page) }}
{{ page.content }}
{% endblock %}
So it extends the base.html template.
Further reading:
Pelican: a static blog generator for
Pythonistas
Pelican - Getting
started
Check out Model–view–controllers