Uri.params not working in frontmatter?

Hello!
I’m new to Grav, absolutely love it so far!
I’ve run into an issue I’m having hard time solving. Let’s say I would like to set the page title to the value of uri.params.
In reality, I want to set the title to particular strings according to the passed values, but let’s omit that for simplicity.
I’ve set pages.frontmatter.process_twig to true in my override of system.yaml, and I have the following page (/test-page):

---
title: "{{ uri.params|e }}"
cache_enable: false
never_cache_twig: true

process:
    twig: true
---

{{ uri.params|e }}

Now, I visit:
https://example.com/test-page/someparam:value

The title is /someparam:value, awesome.
But then, the behavior gets completely unpredictable. I’m rewriting the params in the addressbar to someparam:value1, someparam:value2 etc.
Sometimes, the website is just plain stuck on someparam:value.
Though, it’s not stable. Sometimes, I write say /someparam:value3 and suddenly get /someparam:value1 or /someparam:value2 as the page title without any logic obvious to me.

And interestingly, when I make any change in the default.md and save it, the next load seems to always work as expected.

At the same time, the params displayed in the page content itself are always correct.

Is there anything I could do to get this working? It seems like some sort of caching problem to me, but I’ve both disabled cache_enable and enabled never_cache_twig, are there any other switches I should check?

Thanks!

Hi, @RastislavKish, have you made any progress? I think it’s better if you describe the complete scenario you want to achieve and where you are now, with a code example.

@b.da thanks for asking!
For now, I’ve retracted to a design utilizing static title. It’s not as neat as the dynamic-one, but it works.
Basically, I have a website containing various posts, and I wanted one page that would display all posts of a particular category or a particular tag, which would be used when a user clicks on a category or tag name under an article.
I wanted the page to have a title say: ‘Category blog’, or ‘Tag android’, depending on what the user clicks, sort of like when you make a search on Google and the title bar of your browser displays your request.

My code went originally like this:

---
title: "{{ (uri.param('category')!='') ? ('Category ' ~ uri.param('category'))|e : (uri.param('tag')!='') ? ('Tag ' ~ uri.param('tag'))|e : 'Posts' }}"
cache_enable: false
never_cache_twig: true

content:
    items:
        'page@.descendants': '/posts'
    order:
        by: date
        dir: desc
    limit: 10
    pagination: true

process:
    twig: true
---

{% if uri.param('category')!='' %}
# Category {{ uri.param('category')|e }}

These are all posts in category {{ uri.param('category')|e }}.

{% elseif uri.param('tag')!='' %}
# Tag {{ uri.param('tag')|e }}

These are all posts tagged {{ uri.param('tag')|e }}.

{% else %}

# Posts

{% endif %}

{% include 'partials/collection-list.html.twig' %}

But it didn’t work, because the frontmatter doesn’t seem to be always processed, as I mentioned in my previous post, where the toy page puts uri.params right into the title and at least on my hosting with the latest Grav installed, it behaves as described i.e. displaying wrong values, so the title of the now mentioned example doesn’t even have a chance to be set properly.

The only solution I can think of would be to introduce a new block in the title tag of the base template of the Quark theme (which my own theme derives from). I’m not sure if twig allows nested blocks, but if it does, I could override it afterwards in the page content, which works as expected.
It seems like a bit overkill to me, especially because twig in frontmatter as far as I understand was introduced exactly to make dynamic titles possible, perhaps this could be reported as a bug?
But right now, it seems like the most elegant approach I’m aware of.

@RastislavKish you are close, but indeed, it’s better create custom page template or modify existing one (or create a plugin), instead of trying to put your code in the page file.
just a few questions before i come up with a working solution:

  • all posts of page collection are children of particular page (‘/posts’)?
  • what template from Quark are you trying to use (more suitable in your case) - default, or blog? should it include Quark sidebar, are you using the taxonomylist plugin etc. Maybe you have a screenshot of what you are trying to achieve.
  • did you think what a page without a uri.param in the address bar should display? maybe it’s better to combine the desired functionality with a standard blog page?

Meanwhile you can take a look on Knowledge Base Theme, Project Space Theme, Cascade Filters Plugin and how a similar task was resolved.

So, i decided to modify blog template (which leaves all the benefits, like Blog Config tab, pagination, breadcrumbs controls). Anyway you will get the idea.

  1. copy from Quark blog.html.twig file (quark/templates/blog.html.twig) and put it in your inherited theme in templates folder.
  2. rename the file (if you want to create your own rather than override a blog template). let’s say posts.html.twig (in this case the same for the blog.yaml file (quark/blueprints/blog.yaml) copy/paste/rename to the blueprints folder)
  3. open posts.html.twig file and:
    a. after the last set {% set show_pagination %} add this code
{% set page_title = page.title %}
{% if (uri.param('category') is defined and uri.param('category') is not empty) and (uri.param('tag') is defined and uri.param('tag') is not empty) %}
    {% set page_title = 'Category' ~ ': ' ~ uri.param('category')|capitalize ~ ' with ' ~ 'Tag' ~ ': '~ uri.param('tag')|capitalize %}
{% elseif uri.param('tag') is defined and uri.param('tag') is not empty %}
    {% set page_title = 'Tag' ~ ': '~ uri.param('tag')|capitalize %}
{% elseif uri.param('category') is defined and uri.param('category') is not empty %}
    {% set page_title = 'Category' ~ ': '~ uri.param('category')|capitalize %}
{% endif %}

b. then replace the {% block hero %} code with:

{% block hero %}
   {% set content %}
        <h1>{{ page_title|e }}</h1>
    {% endset %}
    {% if blog_image %}
        {% include 'partials/hero.html.twig' with {id: 'blog-hero', hero_image: blog_image} %}
    {% else %}
        {% include 'partials/hero.html.twig' with {id: 'blog-hero'} %}
    {% endif %}
{% endblock %}
  1. you can also modify blueprint, but just manually change Blog Route in admin to (/posts)

  2. it’s not the best solution for Google (you’ll need more complex code), but you can also put the results in the <title> tag by overriding {% block head %}.
    add the code after the page_title set (3.a)

{% block head deferred %}
    <meta charset="utf-8" />
    <title>{% if page_title %}{{ page_title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% include 'partials/metadata.html.twig' %}
    <link rel="icon" type="image/png" href="{{ url('theme://images/favicon.png') }}" />
    <link rel="canonical" href="{{ page.url(true, true) }}" />
{% endblock head %}

to prevent Google from indexing pages that contain uri.params, add to the head block

{% if uri.params is not empty %}
	<meta name="robots" content="noindex">
{% endif %}

for multilingual site page_title set for category could look like this
{% set page_title = 'SITE.CATEGORY'|t ~ ': '~ uri.param('category')|capitalize %}

then put the translation in the languages.yaml file in theme folder

en:
  SITE:
    CATEGORY: Category