Drupal8 retain quick edit functionality when inserting content from node variable - twig

I have this markup in my twig file.
<div class="post-title-block ilb">
<h2 class="thin">{{ node.title.value }}</h2>
</div>
I would like to retain Drupal quick edit functionality.
Where how how to I wrap {{ attributes }}, {{ title_prefix }}, {{ title_suffix }} etc.. ?
My twig file lives in templates/content/node--posts-full.html.twig

You've indicated a node template, which means you will add {{attributes}} to a block element that surrounds the field content, and add the prefixes just after the same element so that the quickedit module can inject it's markup towards the top of the block.
Presuming the above is your template, you could do:
<section{{ attributes }}>
{{ title_prefix }}
[you could wrap an actual title here...]
{{ title_suffix }}
<div class="post-title-block ilb">
<h2 class="thin">{{ node.title.value }}</h2>
</div>
</section>

Related

How can I convert this TPL or PHP condition to a valid condition?

I would like to add a condition to my twig file, but I can only find code examples for TPL or PHP. All my attempts to translate this into twig syntax have so far been unsuccessful. This may also be due to the fact that these examples are no longer up-to-date. Unfortunately, there is little current information about the open source vanilla forum. But as long as I don't even know if my twig syntax should actually work, I can't say that.
Can someone please help me and tell me if my twig syntax is correct?
Thank you for help!
This is what the relevant part of my twig looks like (I only want to display the main panel for Signed In users):
<div class="Frame-details">
{% if not isHomepage %}
<div class="Frame-row">
<nav class="BreadcrumbsBox" aria-label={{ t("Breadcrumb") }}>
{{ renderBreadcrumbs() }}
</nav>
</div>
{% endif %}
<div class="Frame-row">
<!-- Main Content -->
<section class="Content MainContent">
{{ renderControllerAsset("Content") }}
</section>
<!-- Main Content END -->
<!-- Main Panel -->
{% if UserSignedIn %}
<div class="Panel Panel-main">
{{ renderControllerAsset("Panel") }}
</div>
{% endif %}
<!-- Main Panel END -->
Here are the examples I've found so far:
For TPL is the following example:
{if $User.SignedIn}
Do some coding like show the Panel Asset
{/if}
For PHP is the following example:
$Session = Gdn::Session();
if ($Session->IsValid())
{
Show the Panel Asset
} else
{
Show only the Guest Box asset

Out putting RAW ACF values in twig/timber unto page header for SEO purposes

So, from ACF I have created my own SEO fields in my custom WP theme, so I don't have to rely on a plugin, and I want to have the default values already filled out, so we don't always have be doing that unless for something specific - how do I out put those unto my page and insert them in the header at the same time? I have tried {{post.meta_description|raw}} and {{ function('wp_head') }} timber but it just prints it on the page, what am I missing?
Another great {{ post.tool_brand }} {{ post.tool.type}}
for sale, {{ post.power_type }} of power with a
competitive price {{ post. tool_price }}!
{% extends "base.twig" %}
{% block content %}
<div class="container my-4">
<head>
{{post.meta_description|raw}}
{{ function('wp_head') }}
</head>
</div>
{% endblock %}
This here seems to do exactly what I wanted it to do: {{ include(template_from_string(post.meta_description)) }}
ie: <meta name="description" content="{{ include(template_from_string(post.meta_description)) }}">

Shopify Liquid: Paginating blog post based on tag

I'm going to try my best to explain this, sorry if it seems confusing.
I have a customized theme. I'm trying to take articles from the blog and put them into 7 separate tagged pages. Essentially to create separate blog templates standard one blog template. The pages bring in a section that paginates by 6.
I'm able to bring the blog articles into the section and paginate, but I'm unable to filter out the unnecessary tags. When I use if/unless statements inside the pagination loop, it just didn't render the unnecessary ones but still paginated based on it, so I had 3 articles on the first page, 2 on the second, and so on. Which make sense why it would do that.
I've tried the 'where' filter on my assign tag and the paginate tag, didn't work. When I asked on the Shopify Slack someone mentioned using the Section Render API with the endpoint '/blogs/{blog_id}/tagged/{tag_id}' but the returns all of the HTML from that page and I don't know how I'd parse and paginate over that. The Section Render API documentation is wanting, to say the least. And my experience with APIs is limited
The closest I've come to answer an is this answer: https://stackoverflow.com/a/60000460/12948634
The problem with the liquid solution is that I can apply a "view" to the tagged posts page but I still have to paginate over it. I still have to use the {% paginate blog.articles %} that apparently doesn't filter. Pagination isn't included in this theme and I'm not quite sure how to add that that to my 'blog-content.liquid' file without disturbing the main tagged page.
Any ideas? Code below:
<div id="article-index-card-section" class="g-flex">
{% assign blog = blogs.{blog_id} %}
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
I will probably go the JS route in this case.
Here is what will I probably do, I don't know if it will fit your needs.
Create a separate blog.ajax.liquid template
We will create a new blog template and we will keep only the HTML need for the page to make the request faster and strip unused HTML elements.
{% layout none %}
<div id="article-index-card-section" class="g-flex">
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
That's why we add the line {% layout none %} at the top to remove all of the HTML output from the default layout and only output the HTML on the template we create.
Make fetch request to that new template
We make a fetch request to the blog but we must specify that it must used the newly created template and not the default one.
fetch('/blogs/{blog_handle}/tagged/{tag}?view=ajax').then(res => res.text()).then(res => {
document.querySelector('.blog-holder').innerHTML = res;
})
For that we add the ?view=ajax to the end of the request, where the ajax part is the name of the template we created after blog.ajax.liquid.
This request needs to be done for each separate blog, so if you have 10 blogs you will do this request 10 times for each one.
Pagination request
The pagination request will be similar to the request of the blog but you will need to add the page=2 argument to the request where the 2 is the page number.
So something like so:
fetch('/blogs/{blog_id}/tagged/{tag_id}?view=ajax&page=2').then(res => res.text()).then(res => {
document.querySelector('.blog-template').innerHTML = res;
})
Blog main page
I will probably create a static section, where you will be able to select which blog goes on this page.
{%- for block in section.blocks -%}
{%- assign _block = block.settings -%}
{%- assign block_blog = _block.blog -%}
<div class="blog-template" data-handle="{{block_blog}}">
</div><!-- /.blog-template -->
{%- endfor -%}
<script>
document.querySelectorAll('.blog-template').forEach(item => {
const handle = item.getAttribute('data-handle');
// make fetch request and the logic for your tags
})
</script>
{% schema %}
{
"name": "Blogs",
"blocks": [
{
"type": "blog",
"name": "Blog",
"settings": [
{
"type": "blog",
"id": "blog",
"label": "Choose a blog"
}
]
}
]
}
{% endschema %}
This will be my personal choice of direction I go, I don't know if it will fit your needs.

Unique page identifiers in Grav CMS

I'm using the Grav CMS to create a modular web page; however, I'm having difficulty customizing the layout based on how the content is generated.
I've followed the documentation found Grav main site from which I've model my site after.
My folder structure is essentially:
pages
01.home
_section1
_section2
In each section folder I have my .md file. And each section is considered a sub-page of 'home'.
I've created the template file, modular.html.twig, in which I have the following code:
{% extends 'partials/base.html.twig' %}
{% block content %}
{% for child in page.children() %}
{{ child.content() }}
{% endfor %}
{% endblock %}
This code iterates through sub-pages to load the content onto the home page. In my template I'm simply printing the result of the content using {{ content }}
What I end up with is a page with vertically stacked content and repeating html,
as such.
What I want to do is uniquely define each sub-page (section) so that I can manipulate the content differently in my html, as such.
I've thought about creating separate template files for each section, but much of my content is nested.
For instance I have something akin to:
<div class="row">
<div class="section-1">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
<div class="section-2">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
</div>
Is it possible to accomplish what I'm trying to do with this framework? If so, how might I go about it?
Thank you
I think there are many ways to do this. For me, I use page's header to set CSS class of each section.
My section's md files could look like this (for example mysection.md)
---
title: Section 1
section_class: section-1
---
This is the content of section 1.
Here is my modular.html.twig:
{% extends 'partials/base.html.twig' %}
{% block content %}
<div class="row">
{% for child in page.children() %}
<div class="{{ child.header.section_class }}">
{{ child.content() }}
</div>
{% endfor %}
</div>
{% endblock %}
In my mysection.html.twig I print the section's content
<h1>{{ page.content }}</h1>
I hope this helps.

Cancelling parent template if variable is null in Twig

I'm new to Twig and I'm trying to figure out how to achieve the following.
I have an object with a set of properties that I want to render with different Twig templates depending on which type of property it is (text, images, date, etc).
I want to render them as follows:
<div class="row">
<div class="title">Title of property</div>
<div class="propertycontent">
//Specific property content depending on property type
</div>
</div>
My problem is that I can't figure out to skip the complete output if the property is not defined. I want to be able to use parent templates to take care of the "wrapping" of the rendered property content. Is it possible to use parent templates that returns nothing if the property value is undefined? Is there another good solution that does not rely on include "begin"/"end" for wrapping each template?
Thanks in advance.
Solution: Call parent with value(might be null) and title
Parent (propery_wrapper.twig):
{% if value %}
<div class="row">
<div class="title">{{title}}</div>
<div class="propertyContent">
{% block content %}{% endblock %}
</div>
</div>
{% endif %}
child (for height property):
{% extends 'property_wrapper.twig' %}
{% block content %}
{{ value.value|number_format(2, ',') }} m
{% endblock %}

Resources