Twig how to check which template is geting rendered - php

I have
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include '/layouts/navbar.html.twig' %}
</div>
{% block body %}{% endblock %}
</div>
</div>
Now in this /layouts/navbar.html.twig theres an anchor tag, who's href attribute heavily depends on which template is rendered below, for example if its the Posts template, the href should be /posts/new, if its the announcements template, the href should be /announcements/newand so on, is that even possible?

You could make use of the global variable _self to solve this e.g.
main.twig
{% include "foo.twig" %}
{% include "bar.twig" %}
foo.twig and bar.twig
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'template': _self, } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
nav.twig
{% set path = '' %}
{% if template == 'foo.twig' %}
{% set path = 'path/to/foo' %}
{% elseif template == 'bar.twig' %}
{% set path = 'path/to/bar' %}
{% endif %}
{% for i in 0..3 %}
{{ i }}
{% endfor %}
demo

If the path is the only thing that depends on the current template, I'd modify DarkBee's example to just simply pass the path from the parent template. That way you don't need the if/else structure:
posts.twig:
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'path': '/posts/new' } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
announcements.twig:
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'path': '/announcements/new' } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
nav.twig:
{% for i in 0..3 %}
{{ i }}
{% endfor %}

Related

How to overwrite a html-element but keep the rest of a block?

I am extending a twig-template where i want to replace the line
<div class="container">
with
<div class="container-fluid">
Twig-template
{% block layout_main_navigation %}
<div class="main-navigation"
id="mainNavigation"
data-flyout-menu="true">
{% block layout_main_navigation_navbar %}
<div class="container"> <!-- This line should be replaced -->
{% block layout_main_navigation_menu %}
...
{% endblock %}
...
{% endblock %}
...
{% endblock %}
I tried to overwrite the layout_main_navigation by copying everything and changing the class of the div. But i am not happy with that solution as i have to copy and overwrite a lot blocks.
How can i achieve replacing the class of the div and overwrite as less block as possible?
You can override the block layout_main_navigation_navbar, add the div element with the desired class container-fluid and then include the original content of the block layout_main_navigation_menu using the parent() function:
{% block layout_main_navigation_navbar %}
<div class="container-fluid">
{% block layout_main_navigation_menu %}
{{ parent() }}
{% endblock %}
</div>
{% endblock %}

WordPress/Timber post loop looping four times

I have the following code in my theme's index.php file. It is set to grab four of the most recent posts from a selection of category IDs. The IDs are a mix of parent and children categories.
$args = array(
'cat' => '7,5,3,4,6',
'numberposts' => 4,
'order' => 'DESC',
);
$context['stories'] = Timber::get_posts($args);
The following code is used in the tease.twig file.
{% block content %}
{{ post.content }}
{% endblock %}
The following code is used in the tease-stories.twig file.
{% extends "tease.twig" %}
{% block content %}
{% for story in stories %}
<article class="story" id="story-{{post.ID}}">
{% if loop.first %}
{% if story.thumbnail.src %}
<img src="{{story.thumbnail.src}}" class="" alt="" />
{% endif %}
{% endif %}
<h3 class="story__heading">
<a href="{{ story.link }}">
{{ story.title }}
</a>
</h3>
<div class="story__meta">
<time class="">{{ story.date }}</time>
</div>
{% if loop.first %}
<div class="story__content">
{{ story.preview.read_more(false) }}
</div>
{% endif %}
</article>
{% endfor %}
{% endblock %}
The following code is used in the index.twig file.
{% extends "base.twig" %}
{% block content %}
<section class="stories">
<h2>Latest Travel Stories</h2>
{% for story in stories %}
{% include ['tease-stories.twig'] %}
{% endfor %}
</section>
<section class="observations">
<h2>Observations</h2>
{% for observation in observations %}
{% include ['tease-observations.twig'] %}
{% endfor %}
<a href="{{ site.url }}/gerry/observations" title="More observations" class="more more-observations">
More Observations
</a>
</section>
{% endblock %}
Screenshot of looped content:
I am not sure why the loop is looping over the content four times. Any help is greatly appreciated. Cheers.
I have solved the problem with assistance from #DarkBee. The problem was using a for loop twice, once in the index.twig file and once in the tease.twig file, which resulted in the stories being outputted multiple times. My updated index.twig code is below.
{% extends "base.twig" %}
{% block content %}
<section class="stories">
<h2>Latest Travel Stories</h2>
{% include ['tease-stories.twig'] %}
</section>
<section class="observations">
<h2>Observations</h2>
{% include ['tease-observations.twig'] %}
<a href="{{ site.url }}/gerry/observations" title="More observations" class="more more-observations">
More Observations
</a>
</section>
{% endblock %}

Symfony - How can I omit the first item in a twig template's loop?

I want to display news without first one. How I can achieve this?
Here is code I have to change:
<div class="home-box-news carousel-news slide home-box-shadow" id="news" style="clear: both;">
<ol class="carousel-indicators news-box">
{% for i in 0..news|length-1 %}
{% if loop.index is not divisibleby (2) %}
<li data-target="#news" data-slide-to="{{ i / 2 }}" {% if loop.first %}class="active"{% endif %}></li>
{% endif %}
{% endfor %}
</ol>
<div class="carousel-inner">
{% for item in news %}
{% if loop.index is not divisibleby (2) %}
<div class="item{% if loop.first %} active{% endif %}">
<div class="carousel-caption">
{% endif %}
<h3>{{ item.name }}</h3>
<p class="date">{{ item.createdAt|date('d.m.Y, G:i') }}</p>
<p {% if loop.index is divisibleby (2) %}style="border-bottom: 0;" {% endif %}>{{ item.content[:110]|nl2br }}{% if item.content|length > 110 %}... <a class="more" href="{{ path('home_news_index') }}">czytaj dalej</a>{% endif %}</p>
{% if loop.index is divisibleby (2) or loop.last %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
There is more concise version of what Robert suggested:
{% for item in news[1:] %}
You can use slice filter which works like array_slice() function in PHP.
{% for item in news[1, news.length -1 ] %}
put this in your loop to omit first news
{% if loop.index0 > 0 %}
{# display your news #}
{% endif %}
Of course there is another answer which may/may not be cleaner/simpler/w/e - don't pass the row to Twig in the first place.

Is it possible to use Symfony's base.html without extending it?

I'm using Symfony2 to create a single page application,
as you can see, the base.html.twig (posted below) is relatively small,
all I want to do is create a route '/' that redirects directly to the base.html without the need of using unnecessary bundle inheritance.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %} Share with me {% endblock %}</title>
{% block stylesheets %}
{% include 'assets/basetemplates.html.twig' %}
{% endblock %}
</head>
<body class="metro mybody">
{% block channel %}
<div id="profile_push_container"></div>
<a href="#channel-close">
<div class="profile-modal-overlay"></div>
</a>
{% endblock %}
{% block content_form %}
<div id="content_form_overlay" class="animated fadeIn"></div>
<div id="content_form" class="animated fadeInDownBig">
<div class="content_form">
<button class="content_cancel_btn" onclick="ContentForm.controller.closeForm();"><i class="icon-cancel-2"></i></button>
<div class="form-items" id="form-items">
<div class="form-item">
<h2 class="content_title">Auto handel</h2>
</div>
</div>
</div>
</div>
{% endblock %}
{% block navbar %}
{% include 'GabrielLayoutBundle:Widgets:navigation.html.twig' %}
{% endblock %}
{% block body %}
<div id="content-loop-container">
<div id="content-push-in"></div>
{% block sidebar %}
<aside class="sidebar bounceInLeft animated light" id="custom-sidebar-css">
<ul id="the_sidebar"></ul>
</aside>
{% endblock %}
</div>
<div id="more-button"></div>
{% endblock %}
{% block footer %} {% endblock %}
{% block javascripts %}
{% include 'assets/basescripts.html.twig' %}
{% endblock %}
</body>
</html>
This doesn't seem to work, it finds the template but prevents me from using the twig functions
$collection->add('home_route', new Route('/', array(
'_controller' => 'FrameworkBundle:Template:template',
'template' => '<path>/views/base.html.twig',
)));

Error in nested form and twig display

I have a problem with errors display in my twig templates.
Here is my twig with one nested form form.pictures :
{{ form_start(form) }}
{% if not form.vars.valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.pictures) }}</div>
</div>
{% endif %}
{% for formChild in form.pictures %}
<div class="child">
{% if not formChild.vars.valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.picture) }}</div>
<div class="form-errors">{{ form_errors(form.caption) }}</div>
</div>
{% endif %}
{{ form_widget(formChild.picture) }}
{{ form_widget(formChild.caption) }}
</div>
{% endfor %}
{{ form_end(form) }}
After submission, when a child form is non valid, my parent form is not valid too.
Problem is that it display empty div on top like :
<div class="flash-errors-wrapper">
<div class="form-errors"></div>
</div>
I don't want that because css exist on flash-errors-wrapper class so style is applied.
Any ideas?
You certainly need to check if one child form is not valid when you check if the parent form is valid. One way to do it would be (Untested, it may need some adaptation):
{% if not form.vars.valid %}
{% set all_childs_valid = True %}
{% for formChild in form.pictures %}
{% if not formChild.vars.valid %}
{% set all_childs_valid = False %}
{% endif %}
{% endfor %}
{% if all_childs_valid %}
<div class="flash-errors-wrapper">
{{ form_errors(form) }}
<div class="form-errors">{{ form_errors(form.pictures) }}</div>
</div>
{% endif %}
{% endif %}
I usually display form errors just as described in docs:
{% if errors|length > 0 %}
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}

Categories