how to show a twig collection in grav - twig

My problem is:
If I have a page written this way:
(saved home.en.md)
title: 'Home'
published: true
metadata:
keywords: 'home'
taxonomy:
category: - main
tag: - 'home'
menu: 'Home'
slug: home
process:
twig: true
routable: true
cache_enable: true
visible: true
content:
items: #root
order:
by: date
dir: desc
limit: 10
pagination: true
---
This are all our pages:
how and where do I have to add the twig text?
{% for p in page.collection %}
<h3> {{ p.title }} </h3>
{{ p.summary }}
{% endfor %}

I resolved this by adding
template: name-of-template
and in my themes folder I added a name-of-template.html.twig :
{% extends 'partials/base.html.twig' %}
{% block content %}
<ul>
{% for p in page.collection %}
<h3> {{ p.title }} </h3>
{{ p.summary }} <br>
{{ p.title }} <br>
{# could return http://example.com/my-section/my-category/my-blog-post #}
{% endfor %}
</ul>
{% endblock %}
I hope this will help someone!

Related

twig attrbutes.addclass nesting issue

Apologies if this has been asked before, but I'm on my first week working with Drupal and Twig.
I have the following code:
{%
set container_classes = [
'paragraph',
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
'container'
]
%}
{% set image_classes = [
'col-12'
]
%}
{% block paragraph %}
{% block content %}
<div{{ attributes.addClass(container_classes) }}>
<div class='row'>
<div{{ attributes.addClass(image_classes) }} data-type='image'>
{{ content.field_two_column_image }}
</div>
<div class='col-12 col-lg-auto' data-type='copy'>
{{ content.field_two_column_copy }}
</div>
</div?>
</div>
{% endblock %}
{% endblock paragraph %}
My issue is the nested attributes.addClass. When I look at the HTML, I'm also seeing the container_classes classes, which is not what I'm looking for.
So how can I separate the two?
You can Create Attributes in Twig.
Something like this should work.
{# attributes for container #}
{% set container_attributes = create_attribute() %}
{%
set container_classes = [
'paragraph',
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
'container'
]
%}
{% set container_attributes = container_attributes.addClass(container_classes) %}
{# attributes for image #}
{% set image_attributes = create_attribute() %}
{% set image_classes = [
'col-12'
]
%}
{% set image_attributes = image_attributes.addClass(image_classes) %}
{% block paragraph %}
{% block content %}
<div{{ container_attributes }}>
<div class='row'>
<div{{ image_attributes }} data-type='image'>
{{ content.field_two_column_image }}
</div>
<div class='col-12 col-lg-auto' data-type='copy'>
{{ content.field_two_column_copy }}
</div>
</div?>
</div>
{% endblock %}
{% endblock paragraph %}

Drupal 8 How can I give dropdown links a class?

I'm trying to build a simple dropdown menu on drupal 8 by using twig templates. My problem is that I can't find a way to give the dropdown links a class. Here's my code
{#
/**
* #file
* Theme override to display a menu.
*/
#}
{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0, menu_name) }} {# 1. #}
{% macro menu_links(items, attributes, menu_level, menu_name) %} {# 1. #}
{% import _self as menus %}
{# 1. #}
{%
set menu_classes = [
'c-menu-' ~ menu_name|clean_class,
]
%}
{% if items %}
{% if menu_level == 0 %}
<ul{{ attributes.addClass('navbar-nav u-header__navbar-nav') }}>
{% else %}
<ul class="hs-sub-menu list-unstyled u-header__sub-menu u-header__sub-menu-offset animated">
{% endif %}
{% for item in items %}
{%
set classes = [
menu_level ? 'dropdown-item u-header__sub-menu-list-item' : 'nav-item u-header__nav-item',
item.is_expanded ? 'menu-item',
item.is_collapsed ? 'menu-item',
item.in_active_trail ? 'active',
item.below ? 'nav-item hs-has-sub-menu u-header__nav-item hs-sub-menu-opened',
]
%}
<li{{ item.attributes.addClass(classes) }} data-event="hover" data-animation-in="fadeInUp" data-animation-out="fadeOut">
{%
set link_classes = [
not menu_level ? 'nav-link u-header__nav-link',
item.in_active_trail ? 'active',
item.below ? 'nav-link u-header__nav-link',
item.url.getOption('attributes').class ? item.url.getOption('attributes').class | join(' '),
]
%}
{% if item.below %}
{{ link(item.title, item.url, {'class': link_classes, 'data-toggle': 'dropdown', 'aria-expanded': 'false', 'aria-haspopup': 'true' }) }}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% else %}
{{ link(item.title, item.url, {'class': link_classes}) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
I just need to give a class to {{ menus.menu_links(item.below, attributes, menu_level + 1) }} completely independent from its parents.
Is there a way to achieve it? My output is like this
Sublink
I need to change it like this
Sublink
If there's any other way to do so like with custom module or with hooks, please let me know
Achieved the result with following code
{#
/**
* #file
* Theme override to display a menu.
*/
#}
{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0, menu_name) }} {# 1. #}
{% macro menu_links(items, attributes, menu_level, menu_name) %} {# 1. #}
{% import _self as menus %}
{# 1. #}
{%
set menu_classes = [
'c-menu-' ~ menu_name|clean_class,
]
%}
{% if items %}
{% if menu_level == 0 %}
<ul{{ attributes.addClass('navbar-nav u-header__navbar-nav') }}>
{% else %}
<ul class="hs-sub-menu list-unstyled u-header__sub-menu u-header__sub-menu-offset animated">
{% endif %}
{% for item in items %}
{%
set classes = [
menu_level ? 'dropdown-item u-header__sub-menu-list-item' : 'nav-item u-header__nav-item',
item.is_expanded ? 'expanded',
item.is_collapsed ? 'collapsed',
item.in_active_trail ? 'active',
item.below ? 'nav-item u-header__nav-item expanded nav-item hs-has-sub-menu u-header__nav-item',
]
%}
<li{{ item.attributes.addClass(classes) }} data-event="hover" data-animation-in="fadeInUp" data-animation-out="fadeOut">
{%
set link_classes = [
'nav-link',
not menu_level ? 'u-header__nav-link' : 'u-header__sub-menu-nav-link',
item.in_active_trail ? 'active',
item.url.getOption('attributes').class ? item.url.getOption('attributes').class | join(' '),
]
%}
{% if item.below %}
{% set title %}
{{ item.title }}<span class="fa fa-angle-down u-header__nav-link-icon"></span>
{% endset %}
{{ link(title, item.url, {'class': link_classes, 'data-toggle': 'dropdown', 'aria-expanded': 'false', 'aria-haspopup': 'true' })}}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% else %}
{{ link(item.title, item.url, {'class': link_classes}) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}

Is it possible to use for loop in the include tag?

{% include './partial/project.twig' with {'status': 'Past Project',
'statusClass': 'past',
'heroImage': "/dist/images/projects/project-south16th.jpg",
'logo': '/dist/images/logo-south16th.png',
'desc': '23 three- and four-bed townhomes',
'address': '15885 16 Avenue, South Surrey',
'showGallery': true,
'galleryID': 'south16th',
'link': '#',
'galleryImages': "
{% for i in range(1, 10) %}
<a data-fancybox='south16th' href='{{ theme.uri }}/dist/images/gallery/south16/{{ i }}.jpg'></a>
{% endfor %}
"
} %}
The above code is not valid because it seems like twig doesn't allow nested tag in the include tag? Or did I do something wrong?
Is there another way to achieve it? I would like to repeat this code X times and pass it to the template:
{% for i in range(1, 10) %}
<a data-fancybox='south16th' href='{{ theme.uri }}/dist/images/gallery/south16/{{ i }}.jpg'></a>
{% endfor %}
To achieve this you would need to switch up to embed instead of include
index.twig
{% embed 'include.twig' with { 'theme': { 'uri' : 'https://www.example.com', 'pictures': 10, }, } %}
{% block pictures %}
{% for i in 1..theme.pictures %}
<li><a data-fancybox='south16th' href='{{ theme.uri }}/dist/images/gallery/south16/{{ i }}.jpg'></a></li>
{% endfor %}
{% endblock %}
{% endembed %}
include.twig
<h1>Include</h1>
<h2>{{ theme.uri }} - {{ theme.pictures }}</h2>
<ul>
{% block pictures %}
{% endblock %}
</ul>
twigfiddle
note: variables you'd define in include.twig will also be available inside the embed

variables {% set %} in a skeleton file's 'block' don't get recognized , and can't be used when extnding the file?

I have a symfony3/twig skeleton template
page1/skeleton.twig
{# set default values #}
{% block content %}
{% set test = {
sec1: {
title: "null",
content: 'null'
},
}
%}
{% endblock %}
<ul>
19 {% for sec in test[0:] %}
<li>
<p>{{ sec.title }}</p>
<div>
<p>{{ sec.content }}</p>
</div>
</li>
{% endfor %}
</ul>
I then create a layout template that extends the skeleton with 'real' data
page1/layout.html.twig
{% extends 'page1/skeleton.html.twig' %}
{% block content %}
{% set test = {
sec1: {
title: "title1",
content: 'content2'
},
sec2: {
title: "title2",
content: 'content2'
}
%}
{% endblock %}
But when I generate/publish the page, Symfony fires an error
Variable "test" does not exist in :page1:skeleton.html.twig at line 19
500 Internal Server Error - Twig_Error_Runtime
complaining about the skeleton itself.
That 'test' array is defined in the skeleton. Afaict from reading the docs on 'block', 'extends' & 'set', and can't figure out what exactly the problem is.
What do I need to change to eliminate this error?
blocks in twig have their own variable scope.Variables created inside a block can't be accessed outside of it.
Imo you should only test if the variable exist and otherwise create the default value :
skeleton.twig
{% if not test is defined %}
{%
set test = {
sec1: {
title: "null",
content: 'null'
},
}
%}
{% endif %}
<ul>
{% for sec in test[0:] %}
<li>
<p{{ sec.title }}</p>
<div>
<p>{{ sec.content }}</p>
</div>
</li>
{% endfor %}
</ul>
controller.php
<?php
echo $twig->render('page/page.twig', array(
'foo' => [
'title' => 'title1',
'content' => content1',
],
);
Change this in the file page1/skeleton.twig:
{% for sec in test %}
Then it will work.
I tried it. Make sure you understand why!

Render all fields except the submit in symfony 2.3

I'm overriding Skeleton templates of SensioGeneratorBundle as describred in:
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/index.html#overriding-skeleton-templates
So until here is everything fine.
In one of the templates of SensioGeneratorBundle I have:
# app/resources/SensioGeneratorBundle/skeleton/crud/views/new.html.twig.twig
{% block body %}
{{ "{% block page_title 'Incluir " ~ entity ~ "'%}" }}
{{ "{% block body -%}" }}
{{ '{{ form(form) }}' }}
{% set hide_edit, hide_delete = true, true %}
{% include 'crud/views/others/record_actions.html.twig.twig' %}
{{ "{% endblock %}" }}
{% endblock body %}
This works, but {{ form(form) }} is rendering the submit button, and I want to render the submit button in the record_actions.html.twig.twig.
So my question is: How to render a form without render the submit button? Remembering that i'm trying to do this in the skeleton template, in this moment I don't have the fiels of the form to iterate over it.
Thanks!
The solution for this problem is as follows:
# app/resources/SensioGeneratorBundle/skeleton/crud/views/new.html.twig
{% block body %}
{{ "{% block page_title 'Incluir " ~ entity ~ "'%}" }}
{{ "{% block body -%}" }}
{{ " {{ form_start(child) }}" }}
{{ " {% for child in form %}" }}
{{ " {% if child.vars.name != 'submit' %}" }}
{{ " {{ form_row(child) }}" }}
{{ " {% endif %}" }}
{{ " {% endfor %}" }}
{% set hide_edit, hide_delete = true, true %}
{% include 'crud/views/others/record_actions.html.twig.twig' %}
{{ "{% endblock %}" }}
{% endblock body %}
And inside record_actions.html.twig.twig
# app/resources/SensioGeneratorBundle/skeleton/crud/views/record_actions.html.twig
{{ " {{ form_row(form.submit) }}" }}
{{ " {{ form_end(form) }}" }}
<ul class="record_actions">
<li>
<a href="{{ "{{ path('" ~ route_name_prefix ~ "') }}" }}">
Back to the list
</a>
</li>
{% if ('edit' in actions) and (not hide_edit) %}
<li>
<a href="{{ "{{ path('" ~ route_name_prefix ~ "_edit', { 'id': entity.id }) }}" }}">
Edit
</a>
</li>
{% endif %}
{% if ('delete' in actions) and (not hide_delete) %}
<li>
<form action="{{ "{{ path('" ~ route_name_prefix ~ "_delete', { 'id': entity.id }) }}" }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ '{{ form_widget(delete_form) }}' }}
<button type="submit">Delete</button>
</form>
</li>
{% endif %}
</ul>

Resources