Render a link field inside a paragraph template drupal 8 - twig

I have a paragraph called link. In this paragraph there is a single link field that allows multiple values. In the paragraph-link.html.twig file I want to render all of the links added to the paragraph. Instead I get the same link duplicated as many times as the number of link values. So if I add two links, it renders the first link twice. I also need it to work with external and internal links. Currently it only renders the external links properly (but only ever renders the first one).
{% for item in paragraph.field_link %}
{{ paragraph.field_link.title }}
{% endfor %}
Thanks for the comments, the following is working for external links but not internal ones. Internal link URI renders as "internal:/"
{% for item in paragraph.field_link %}
{{ item.title }}
{% endfor %}

With the help of the comments I was able to get this working as I wanted within the paragraph template. Below is the working code for a Link field that allows multiple values within a paragraph field.
{% for item in paragraph.field_link %}
{{ item.title }}
{% endfor %}

Related

Modifiable pagination on Shopify Collection

I was wondering if there was any way to make pagination user modifiable on the front-end? I've been searching for a solution, but can't find anything similar that addresses this specific problem.
I'm aware that at present, you can assign a limit to the pagination, for example:
{% paginate collection.products by 12 %}
What I'm trying to achieve here is the ability for the user to change the number of products viewable, per page, from a dropdown menu. So for example, the user chooses 24, the page refreshes with the revised pagination limit active on the page.
Any help getting started here would be greatly appreciated. Thanks!
You could create 2 alternate templates called 12 collection.12.liquid and 24 collection.24.liquid which would paginate by 12 and 24, respectively. All your templates will be below:
collection.liquid:
{% paginate collection.products by 20 %}
{% include ‘collection-template’ %}
{% endpaginate %}
collection.12.liquid:
{% paginate collection.products by 12 %}
{% include ‘collection-template’ %}
{% endpaginate %}
collection.24.liquid:
{% paginate collection.products by 24 %}
{% include ‘collection-template’ %}
{% endpaginate %}
Then you could create links to those other templates using the view parameter.
<a href=”http://myshop.com/collections/shirts?view=12”>12 per page</a>
<a href=”http://myshop.com/collections/shirts?view=24”>24 per page</a>
More detail, please refer this link here

How to push values to array in templates and partials to output them in layout?

We are using Twig as our templating engine but I'm stuck with a problem of the rendering order now. See - https://straightupcraft.com/articles/twig-processing-order
We are using amp for our new site and with amp and web components in general it is necessary to import the components (once) to use them. So the idea was to create a Twig Extension to accomplish exactly this. Everytime a component is used it is called via this twig function call. The function is checking the component, adding it to a stack and you can use it from now on. The stack then is transformed into a list of imports for the head of the page.
The problem here is Twigs top to bottom rendering. When I call said function in a partial or a template the rendering of "layout.twig" already took place and all function calls below/after are not affecting the stack.
Is there an option to change the rendering to inside out, so that the rendering is first using the lowest partial and "bubbles" up to templates and finally layout without them rendering before?
Another way to get the values in layout would nice as well.
Desired behavior:
Layout.twig
{{ getAllComponents() }}
{# should output component1 and component2 #}
{% block content %}
Page.twig
{% extends Layout.twig %}
{{ addComponent('component1') }}
{% include partials.twig %}
<component1>...</component1>
partials.twig
{{ addComponent('component2') }}
<component2>...</component2>
Actual behavior:
Layout.twig
{{ getAllComponents() }}
{# is empty #}
There is no option to change this behavior. However you can use a trick to archive this:
Render your content to a variable before you call getAllComponents()
layout.twig
{% set mainContent %}
{% block content %}{% endblock %}
{% endset %}
{{ getAllComponents() }}
{{ mainContent }}
There actually is a magical solution to this problem -- some genius wrote this Deferred Twig Extension which lets you run some code (output a variable, call a function, etc) in a block near the top of your layout, but wait until the rest of the twig templates have parsed before executing them. There's an example on that github page showing how you can achieve this.
As far as I know, no you cannot switch the rendering of a TWIG template.
However, I would recommend possibly looking at the {% embed %} or {{ render }} tags.
Embed allows specific TWIG files to be placed within others with variables, so you could pass each component into their relevant partials.twig file.
Render allows the use of embedding a separate controller action, so you create a ControllerAction that took in a component variable and renders its own TWIG file.
Documentation on Embed: https://twig.sensiolabs.org/doc/2.x/tags/embed.html
Documentation containing Render: https://twig.sensiolabs.org/doc/2.x/api.html

Accessing individual fields in Drupal 8 views templates

I'm having trouble doing something that I think should be relatively simple drupal 8 views.
I have a content type called Countries. I would like to display the 3 latest country nodes on my homepage in a views block. Each country is displayed with the class "views-row" on the container div. I am using views--view--unformatted--countries--block_1.tpl to template the output.
I would like to output something like the following markup:
<a class="view-row-1" href="/link/to/node">
<img src="source-of-teaser-image.png">
<h3>Title of node</h3>
</a>
<a class="view-row-2" href="/link/to/node">
<img src="source-of-teaser-image.png">
<h3>Title of node</h3>
</a>
<a class="view-row-3" href="/link/to/node">
<img src="source-of-teaser-image.png">
<h3>Title of node</h3>
</a>
The problem I'm having is accessing individual fields in the template. If I use a view mode, I can access individual fields. If I select "show fields" in the view, I can add a field for "view result counter" and "path", which would allow me to add the "view-row-N" class and link the a tag to the node, but I can't get access to the fields individually. I have the {{row.content}} variable, but any attempt to dig further into the variable (eg row.content.field_name) gives me nothing and calling a {{dump(row.content)}} crashes the website.
I can't output this as a view mode for 2 reasons. I don't have access to the "view result counter" or "path" fields in a view mode and, even if I had these variables, some fields would be nested inside others (The image and title are nested inside the )
I feel this should really be as simple as
<a class="view-row-{{ row.content.view_result_counter }}" href="{{ row.content.path }}">
etc but I've tried everything I can think of. Am I completely on the wrong path? Twig and I are not getting along so far...
I have figured a way using kint.
Inside your views-view-unformatted.html.twig use the following code to display your individual fields:
{% for row in rows %}
{{ row.content['#view'].style_plugin.render_tokens[ loop.index0 ]['{{ YOUR_FIELD_NAME }}'] }}
{% endfor %}
Using content/view mode works in your case.
1/ In "views-view-unformatted.html.twig" you can use "loop.index" in the "for" loop to get index of the current row and add it to the "row_classes" variable.
2/In the twig template for the node you can use something like :
<a href="{{ path('entity.node.canonical', {'node': node.id}) }}">
{{ content.field_img }}
{{ node.getTitle()}}
</a>
3/You will probably get extra html but you can get rid of most of it by overriding relevant templates.
I am not sure if it's what you expect, but you can override field template:
Enable Twig debugging: https://www.drupal.org/node/1903374
Inspect your page in browser (if site is in debug mode there are comments in html with paths to templates for each element).
For example this is field template: core/themes/stable/templates/views/views-view-fields.html.twig
Copy required template into your theme folder
Add or modify markup.
You can debug template using {{ dump(variable) }} or {{ kint(variable) }}
In your case you should be using views-view-fields--countries--block_1.html.twig instead of views-view-unformatted--countries--block_1.html. twig file.
Views fields template will iterate on all rows of result. Your views-view-fields--countries--block_1.html.twig should contain below code -
<div>
<a class="view-row" href="{{variable-to-print-path }}">
<img src="{{ image-path }}">
<h3>{{ fields.title.content</h3>
</a>
</div>
You can check the fields array by using kint function like - {{ kint(fields) }}
Check for image path and anchor path variable from output of kint function.
If you want to do this in views-view-unformatted--countries--block_1.html. twig, then you can access the field values like below -
{% for row in rows %}
{% set photo = file_url(row['content']['#row']._entity.field_page_photo.entity.fileuri) %}
<li><img src={{ photo }} class="img-responsive img-circle"></li>
{% endfor %}
The solution is simple use the views fields template.
I created a new template under themes/templates folder:
views-view-fields--VIEW-NAME.html.twig
And now you can access your fields values like this:
{{ fields.field_NAME.content }}
If you want to access Individual fields in Views Twig Template along with Row Information,
Override Views Fields Template in your custom theme :
views-view-fields--VIEW-NAME.html.twig
To get the row index in the same file, Use :
{{ row.index }}

Paginate Shopify blog with offset? (Liquid)

I'm trying to figure out how to paginate a blog starting at a specific offset. For example, the first page features posts 5-8, the second page 9-12, third page 13-16, and so on. This doesn't seem to work, but I'm looking for something along these lines -
{% paginate blog.articles offset:4 by 4 %}
{% for article in blog.articles
...
{% endfor %}
{% endpaginate %}
Are there any workarounds here?
I was trying to see if there's any way I could find a decent workaround in Liquid but there isn't, since you're offsetting a full page; it'd be perfectly possible to show 5-8 on the first page, but you'd need to show 9-16 on second page and so on and so forth. I'm afraid Shopify paginate won't help you here.
There could be specific workarounds for your situation; please give us more detail and we'll see. For example, if you always want to show the four latest blog articles on every page, and leave pagination handle the rest, a possible way would be to do something as per the following:
{% for article in blogs.news.articles limit: 4 %}
{{ article.title }}
{% endfor %}
{% paginate blog.articles by 4 %}
{% unless paginate.current_page == 1 %}
{% for article in blog.articles %}
{{ article.title }}
{% endfor %}
{% endunless %}
{% include 'pagination' %}
{% endpaginate %}
So outside of any pagination go through the handle to obtain the latest 4 to feature them, and if you're not on page 1, use pagination to print 4 more articles on each page.
If not, this is one of the scenarios where you should consider exposing your own service that internally calls and retrieves articles from the Shopify API as per your needs.
The offset should be specified in your loop parameters, not in pagination.

Combining optional block with element in twig

In defining a base template in twig, I want to reserve an area for special notifications, using a block. It could be an extra sidebar that may contain all kinds of things (calendar, or some extra information, whatever.) The default should be emtpy, but any child template may extend and fill it.
Now I want to have all those extensions be included in a <div class='special-sidebar'> if the block is extended, and not show anything if it is not included. Is there any way to define the containing element in the base template?
{# Base template #}
Content etc...
{% block special %} {# may be overridden by child template #}{% endblock %}
{# child template #}
{% block special %} Here, the special sidebar is filled! {% endblock %}
The base page should show just the content:
// base template:
Content etc...
And the child page:
// child template
Content etc...
<div class"special-sidebar"> Here, the special sidebar is filled! </div>
Where and how do I put the html for this? I could define it in every child, but that means you have to remember to use the correct html each time, I'd rather set this in the base template and not bother with it. But I don't want empty elements in my page if the block is not overridden.
You can solve it like this, if you want to display a certain block only if it has content. Hope, this is what you're looking for.
Example index.html.twig
{% set _block = block('dynamic') %}
{% if _block is not empty %}
{{ _block|raw }}
{% endif %}
Example part.html.twig
{% extends "index.html.twig" %}
{% block dynamic %}
Block content goes here.
{% endblock %}
Source: How to check if a block exists in a twig template - Symfony2

Resources