How to print common capital letter for posts 11ty? - collections

I have posts in my 11ty blog - books, whose names started on some letters. For example, i have 12 books: 4 with first letter "A", 4 with first letter "F", 4 with first letter "Q".
And I have a code for printing all books (I use njk in blog layouts):
<div>
{% for book in collections.books %}
<a class="book" href="{{ book.url }}">
<article>
<h3 class="text-link">
{{ book.data.name }}
</h3>
<p>{{ book.data.text }}</p>
</article>
</a>
{% endif %}
{% endfor %}
</div>
I need to print in front of all books with the letter "A":
<h2>A</h2>
Аfter that there will be 4 books with the letter "A". And after this books, will be the same heading, but with letter "F":
<h2>F</h2>
How to do it? In njk, it is difficult to assign/rewrite and manipulate variables. Maybe there is some normal example?

You can use Nunjucks's set tag to create and modify a variable that keeps track of the previous initial letter:
<div>
{% set previousInitial = null %}
{% for book in collections.books %}
{% if book.data.name[0] != previousInitial %}
<h2>{{ book.data.name[0] }}</h2>
{% endif %}
{% set previousInitial = book.data.name[0] %}
<a class="book" href="{{ book.url }}">
<article>
<h3 class="text-link">
{{ book.data.name }}
</h3>
<p>{{ book.data.text }}</p>
</article>
</a>
{% endfor %}
</div>
Demo:
const data = {
collections: {
books: [
{ data: { name: 'ABC Book', text: 'Learn the alphabets!' }, url: '/book/abc-book/' },
{ data: { name: 'Another A book', text: 'A nice book' }, url: '/book/another-a-book/' },
{ data: { name: 'Foo...', text: '...bar and baz' }, url: '/book/foo/' },
],
},
}
const template = `
<div>
{% set previousInitial = null %}
{% for book in collections.books %}
{% if book.data.name[0] != previousInitial %}
<h2>{{ book.data.name[0] }}</h2>
{% endif %}
{% set previousInitial = book.data.name[0] %}
<a class="book" href="{{ book.url }}">
<article>
<h3 class="text-link">
{{ book.data.name }}
</h3>
<p>{{ book.data.text }}</p>
</article>
</a>
{% endfor %}
</div>
`
console.log(nunjucks.renderString(template, data))
.as-console-wrapper { max-height: 100% !important; }
<script src="https://unpkg.com/nunjucks#3.2.3/browser/nunjucks.min.js"></script>
If the items in collections.books are not already sorted by their names, you can sort them with Nunjucks's sort filter:
{% for book in collections.books|sort(attribute='data.name') %}
An alternative is to create a new collection. Consider creating a collection of books already categorized by their initial letters, so you can reduce the amount of logic in your Nunjucks template. Example of how the new collection and template could look like:
const data = {
collections: {
booksCategorizedByInitialLetters: {
A: [
{ data: { name: 'ABC Book', text: 'Learn the alphabets!' }, url: '/book/abc-book/' },
{ data: { name: 'Another A book', text: 'A nice book' }, url: '/book/another-a-book/' },
],
F: [
{ data: { name: 'Foo...', text: '...bar and baz' }, url: '/book/foo/' },
],
},
},
}
const template = `
<div>
{% for initialLetter, books in collections.booksCategorizedByInitialLetters %}
<h2>{{ initialLetter }}</h2>
{% for book in books %}
<a class="book" href="{{ book.url }}">
<article>
<h3 class="text-link">
{{ book.data.name }}
</h3>
<p>{{ book.data.text }}</p>
</article>
</a>
{% endfor %}
{% endfor %}
</div>
`
console.log(nunjucks.renderString(template, data))
.as-console-wrapper { max-height: 100% !important; }
<script src="https://unpkg.com/nunjucks#3.2.3/browser/nunjucks.min.js"></script>
(I'm not sure whether it's possible to create a collection whose type is an object, but IIRC it should be possible.)

Related

How can i put bullet points on all listed items (collapsible content) DAWN

im trying to get bullet points on all listed items on that tab (collapsible content) on dawn theme with shopify. But i managed to get that just on first item, you can check here with preview url: https://1524t2hmp2urghsm-53196980409.shopifypreview.com
and here is part of code reference this issue:
{%- when 'collapsible_tab' -%}
<div class="product__acordion_container">
<div class="product__accordion accordion" {{ block.shopify_attributes }}>
<details id="Details-{{ block.id }}-{{ section.id }}">
<summary>
<div class="summary__title">
{% render 'icon-accordion', icon: block.settings.icon %}
<h2 class="h4 accordion__title">
{{ block.settings.heading | default: block.settings.page.title }}
</h2>
</div>
{% render 'icon-caret' %}
</summary>
<ul>
<li id="ProductAccordion-{{ block.id }}-{{ section.id }}">{{ block.settings.content }}</li>
{{ block.settings.page.content }}
</ul>
</details>
</div>
</div>
https://ed.codes/blogs/tutorials/add-a-youtube-video-inside-collapsible-row-block-accordion-on-shopify-product-page use this vid to add the element to the block
then add a container in the liquid
<p>
{% if product.metafields.custom.METAFIELDNAME %}
<div class="product-features__features Container">
{{product.metafields.custom.METAFIELDNAME}}
</div>
{% endif %}
</p>
and then link to the HTML formatted list as a multi-line text meta field.

Flash message in symfony 3.4

I'm trying to set flash message from ContactAction then redirect on Homepage, but on it, I can't see my flash message, maybe my session is reset ? Can I have some help, I'm a beginer on Symfony.
CoreController that contain both index and contact functions :
<?php
namespace OC\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class CoreController extends Controller
{
public function indexAction()
{
$ServiceAdverts = $this->container->get('oc_core.listAdverts');
$adList = $ServiceAdverts->getListAdverts();
return $this->render("OCCoreBundle:Core:index.html.twig", array(
'listAdverts' => $adList
));
}
public function contactAction()
{
$this->addFlash('info', 'Contact page not ready yet !');
return $this->redirectToRoute('oc_core_homepage');
}
}
Twig template (homepage) :
{% block body %}
<div>
Messages flash :
{% for msg in app.session.flashBag.get('info') %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endfor %}
</div>
<h2>Liste des annonces</h2>
<ul>
{% for advert in listAdverts %}
<li>
<a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
{{ advert.title }}
</a>
par {{ advert.author }},
le {{ advert.date|date('d/m/Y') }}
</li>
{% else %}
<li>Pas (encore !) d'annonces</li>
{% endfor %}
</ul>
Contact
{% endblock %}
Symfony 3.3 made improvements to flash messages so your Twig template should look different. The app.session.flashBag.get() call is now replaced by app.flashes().
So your Twig code would now be:
{% for msg in app.flashes('success') %}
<div class="alert alert-success">
{{ msg }}
</div>
{% endfor %}
Try this, works for me in 3.2 and 3.4
{% for type, flash_messages in app.session.flashBag.all %}
{% for msg in flash_messages %}
<div class="alert alert-{{ type }}">
{{ msg }}
</div>
{% endfor %}
{% endfor %}
Another thing is that once you called the flashBag it turns empty so you can't use it twice. Check your code that it hasn't been called on another page right before a second redirect ...

Benefit Symfony/Twig i18n from VueJs component

I use Symfony3 with Twig template and VueJs 2.
My symfony controller returns a Twig view with Articles component :
{% extends 'base.html.twig' %}
{% block body %}
<Articles></Articles>
{% endblock %}
And my Articles.vue component :
<template>
<section class="articleapp">
<header>
<h1>Mes articles</h1>
</header>
<div class="main">
<li class="article" v-for="article in articles">
{{ article.title }}
</li>
</ul>
</div>
</section>
</template>
<script>
export default {
data () {
return {
articles: [{title: "Voici le nom d'un article"}]
}
}
}
</script>
I would like translate my title "Mes articles" with Sf/Twig i18n like {{ "Mes articles"|trans({}, "") }} to benefit of translate catalogs.
With Single page component it's impossible.
But with X-Template, the problem can be resolve :
index.html.twig :
{% extends 'base.html.twig' %}
{% block title %}{{ "Mes posts"|trans({}, 'app') }}{% endblock %}
{% block body %}
<div id="app">
<post-form></post-form>
</div>
{% endblock %}
{% block components %}
{{ include("components/form.html.twig", {"form": form }) }}
{% endblock %}
components/form.html.twig :
<script id="post-form-template" type="text/x-template">
<div>
{{ "Mon formulaire"|trans({}, '') }}
{{ form(form) }}
<h1>${ greetings }</h1>
</div>
</script>
And my app.js :
import Vue from "vue";
import VueResource from "vue-resource"
Vue.use(VueResource);
Vue.component('post-form', {
delimiters: ['${', '}'],
template: '#post-form-template',
data: function () {
return {
greetings: 'Hello'
};
}
});
new Vue({
delimiters: ['${', '}'],
el: "#app"
});

How to Limit The Size of Div in Twig

What i Need :
* All div should be of Equal Height and width.
problem im facing
* is some data some div are bigger then another div.
Here is Snapshot Url:
http://postimg.org/image/bxelzcb09/.
Api:
{
data: [
{
id: 42166,
Company_Website: "http://www.amphenol-highspeed.com/",
company_name: "Amphenol High Speed Interconnect",
city_name: "New York",
country_name: "USA",
comp_img: null,
Product_Name: null
},
{
id: 42167,
Company_Website: "http://www.clearfieldconnection.com/",
company_name: "Clearfield, Inc.",
city_name: "Plymouth",
country_name: "USA",
comp_img: null,
Product_Name: null
},
}
code of twig :
{% for item in data.about.data%}
{%if ((loop.index-1)%2)=='0' %}
<div class="row half">
{% endif %}
<div class="6u">
<div class="box panel exhibitor">
<div class="row flush nbdr no-collapse">
<div class="10u name">
<h3>{{item.company_name }}</h3>
<p class="cnt">{{item.city_name }}
{% if item.Company_Website is defined and item.Company_Website is not empty%}
<i class="icon icon-external-link blue bld"></i></p>
{% endif %}
</div>
<div class="2u tar">
{% if item.comp_img is not empty %}
<img width="50" alt="" class="image round lazy" src="{{item.comp_img}}" }}>
{% endif %}
<br class="clear">
</div>
<p class="prod">
{% set foo = item.Product_Name|split(',') %}
{% for i in foo|slice(0, 5) %}
{{ i }} {% if loop.index > 1 %}
,{{ i }}
{% endif %}
{% endfor %}
</p>
</div>
<div class="row flush nbdr pdt">
<div class="12u connect">
<!--<p class="mr"><i class="icon icon-envelope"></i> Connect <span>Booth # 50</span></p>-->
</div>
</div>
</div>
</div>
{%if ((loop.index)%2) == '0' %}
</div>
{% elseif (loop.last) %2 !='0'%}
</div>
{% endif %}
{% endfor %}
{% if data.about.data|length < '30' and request.ajax =='0' %}
{% elseif data.about.data|length < '30' %}
<div class="12u" id="12">
</div>
{% endif %}
i just want size of each div should be equivalent of each .
cases a.) consider 4 div as shown in image
if first div is enrich with data and second infront of enrich div is null with no data.
if first div is enrich with null data and other with big amount of data .
please tell how to resolve this issue , problem is in css or i could solve this issue through coding.
i need all div with or without enrichment of data should be of same size.
i tried to remove spaces i follow link:http://twig.sensiolabs.org/doc/tags/spaceless.html.
any valuable idea are most welcome ?
Maybe you should use CSS as said by DarkBee, or you could use the JS equalizer system of Foundation working fine.
http://foundation.zurb.com/docs/components/equalizer.html

How to add a css class on a "form_row" in twig template

I would like to know how I can add a css class on a "{{ form_row() }}" in twig. For the moment, I have this code :
{{ form_row(form.username, {'label' : "Login", 'attr': {'class': 'loginForm'}}) }}
... But the CSS class "loginForm" isn't used in the HTML code.
Thank you :) !
If you want the common class for the form_row (it means one class for form_label, form_widget and form_errors), you should customize a field_row block.
This article explains how to customize form fields: How to customize Form Rendering.
There are some methods to do this.
For example I'm using Method 2 (How to customize Form Rendering: Method 2):
{% extends 'form_div_layout.html.twig' %}
{% block field_row %}
{% spaceless %}
{% set class='' %}
{% if attr.class is defined %}
{% set class = 'class="' ~ attr.class ~ '"' %}
{% endif %}
<div {{ class }} >
{{ form_label(form, label|default(null)) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock field_row %}
My answer is very similar to nni6's but it allows you to pass through the entire attr array.
My HTML structure is for Twitter Bootstrap but you can have whatever you want. This example also places an error class on the wrapper div if there are any errors - this part is not required but is useful if you use Bootstrap:
{% extends 'form_div_layout.html.twig' %}
{% block field_row %}
{% spaceless %}
{% set field_row_classes = ['control-group'] %}
{% if errors|length > 0 %}
{% set field_row_classes = field_row_classes|merge(['error']) %}
{% endif %}
<div class="{{ field_row_classes|join(' ') }}">
{{ form_label(form, label|default(null)) }}
<div class="controls">
{{ form_widget(form, { 'attr' : attr|default({}) }) }}
{{ form_errors(form) }}
{% if help is defined %}
<p class="help-block">{{ help }}</p>
{% endif %}
</div>
</div>
{% endspaceless %}
{% endblock field_row %}
The difference here is that I'm calling form_widget with the attr array (if it was specified, defaults to {})
Now you can set up your form as normal but pass through a custom class:
{{ form_row(myentity.myproperty, { 'label' : 'mylabel', 'attr' : { 'class' : 'myclass' }}) }}
This post need an update !
Since Symfony 4.3, the row_attr option permits to add attributes (and so, some class). Let's check those links :
Here :
https://symfony.com/blog/new-in-symfony-4-3-more-form-improvements#row-attributes-in-form-themes
or more specifically : https://symfony.com/doc/current/reference/forms/types/form.html#row-attr
I use this code to configure bootstrap in symfony
{% block field_row %}
{% spaceless %}
<div class="control-group {% if errors|length > 0 %}error{% endif %}">
{{ form_label(form, label, { 'attr': { 'class': 'control-label' } }) }}
<div class="controls">
{{ form_widget(form, { 'attr' : attr|default({}) }) }}
{{ form_errors(form) }}
</div>
</div>
{% endspaceless %}
{% endblock field_row %}
The easiest way to accomplish this without overwriting blocks is this:
{% set attr = {'class' : form.myElement.vars.attr.class ~ ' addedClasses...', 'style' : form.myElement.vars.attr.style ~ '; addedStyles...'} %}
{{- form_row(form.myElement, {'attr' : attr}) -}}

Resources