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 %}
Related
I am looping through an array and would like to add a class if it is the first item.
I have tried
{% if field|first %}
{% if field.first %}
{% if field.first() %}
{% if loop|first %}
{% if loop.first %}
{% if loop.first() %}
none work, please help. (the reason I don't use css pseudo first is that this is a grid layout and I have am doing responsive layout things with it)
{% for field in row.fields %}
<div class="c-product-table__item {% if field|first %}{{ first_item }}{% endif %} ">
<span class="c-product-table__text">{{ field.text }}</span>
</div>
{% endfor %}
I don't know why twig filters are not working, I solved it another way. I set a var and made it blank after first loop
{% set thiscount = 'first_item' %}
{% for field in row.fields %}
<div class="c-product-table__item {{ thiscount }}">
<span class="c-product-table__text">{{ field.text }}</span>
</div>
{% set thiscount = '' %}
{% endfor %}
I'm building a WooCommerce site whilst utilising the Twig templating system along with the Timber WordPress plugin and following along with this guide for the tease template.
However, looking at WooCommerce's own default templates/content-product.php they have this at the very top:
// Ensure visibility.
if ( empty( $product ) || ! $product->is_visible() ) {
return;
}
So I'm thinking that we should be doing the same check in the template file? However I am unsure how to check this value in Twig.
I have tried dump(post.is_visible()) but every one returns (bool) false.
I additionally have no idea where showthumb is coming from and couldn't find much information or docs about this particular setting/attribute.
Edit: Here is my controller: (my-theme/woocommerce/archive-product.php)
$context = Timber::get_context();
$context['shop-sidebar'] = Timber::get_widgets( 'shop-sidebar' );
$posts = Timber::get_posts();
$context['products'] = $posts;
if ( is_product_category() ) {
$queried_object = get_queried_object();
$term_id = $queried_object->term_id;
$context['category'] = get_term( $term_id, 'product_cat' );
$context['title'] = single_term_title( '', false );
}
Timber::render( 'views/woo/archive.twig', $context );
Here is my archive.twig file:
{% extends 'archive.twig' %} {# Base Archive File #}
{% block before_article %}
{% do action('woocommerce_before_main_content') %}
{% endblock %}
{% block below_h1 %}
{% do action('woocommerce_archive_description') %}
{% endblock %}
{% block primary_block %}
{% if products|length > 0 %}
<div class="before-products">
{% do action('woocommerce_before_shop_loop') %}
</div>
<div class="products-wrap">
<div class="products row flex">
{% for post in products %}
<div class="product col-sm-6 col-md-4">
{% do action('woocommerce_shop_loop') %}
{% include ["woo/partials/tease-product.twig"] %}
</div>
{% endfor %}
</div>
</div>
<div class="after-products">
{% do action('woocommerce_after_shop_loop') %}
</div>
{% else %}
<div class="no-products">
{% do action('woocommerce_no_products_found') %}
</div>
{% endif %}
{% endblock %}
{% block after_article %}
{% do action('woocommerce_after_main_content') %}
{{ parent() }}
{% endblock %}
Here is my tease-product.twig file:
<article {{ fn('post_class', ['entry'] ) }}>
{{ fn('timber_set_product', post) }}
<div class="media">
<div class="media-figure {% if not post.thumbnail %}placeholder{% endif %}">
<a href="{{ post.link }}">
{% if post.thumbnail %}
<img src="{{ post.thumbnail.src|resize(600)|e('esc_url') }}" class="img-responsive" />
{% else %}
<span class="thumb-placeholder"><i class="icon-camera"></i></span>
{% endif %}
</a>
</div>
<div class="media-content">
{% do action('woocommerce_before_shop_loop_item') %}
{% do action('woocommerce_before_shop_loop_item_title') %}
{% if post.title %}
<h3 class="entry-title">{{ post.title }}</h3>
{% else %}
<h3 class="entry-title">{{ fn('the_title') }}</h3>
{% endif %}
{% do action( 'woocommerce_after_shop_loop_item_title' ) %}
{% do action( 'woocommerce_after_shop_loop_item' ) %}
</div>
</div>
</article>
How can I retrieve the correct value of the is_visible method?
I reckon OP has solved the problem by now. But, for future reference...
You should be able to do {{ post.is_visible }} to output the value.
Similarly, both if statements below work for me.
{% if (product.is_visible) %}
{% if (product.is_visible()) %}
Now, I am fairly new to WooCommerce and Timber, and I don't know much about is_visible, so I apologize if I am wrong here. But, I know I Am able to use WC_Product member functions in twig templates like {{ variable.function_name }}, ie. {{ product.get_title }} or {{ product.get_price }}, so I expect is_visible to be no different.
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 %}
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.
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',
)));