Dynamic pre-selection of CS Forms Checklist Option

Hi Themeco Team,

I am partially referencing back to my older support request but with a more specific example this time.

Let’s say we have an ACF custom taxonomy Month with all 12 months added as the taxonomy terms. What we need is on page load to grab the current date and to define the current month. Then with respective TWIG Template we compare if it is true or false for each ‘Month’ taxonomy term. That should allow us to pre-populate ‘true’ or ‘false’ value inside Selected option while in Breakout Mode inside CS Forms Checklist Option. In the end, we need just the current month taxonomy term to be pre-selected on page load and maybe also on Clear Filter button flush. But even though the TWIG script works in a text element correctly, it doesn’t work in the ‘Selected’ option in the form. It doesn’t matter if the output is ‘true’ or ‘false’; that item is always chosen as it is in the ‘true’ state when the TWIG template is linked. I do not understand why.


Here instead of false we link respective TWIG template.

And here is the TWIG template script for January only:

{% set month = global.date|date('m') %}
{% if month == 01 %}
      true
{% else %}
      false
{% endif %}

Ideally we need another TWIG script that will check each taxonomy term in the Loop dynamically and put true or false for its each Selected option, no matter what month it is. Probably {{ term.slug }} should be involved somehow to make it possible. I am not sure how to properly debug such a code when the TWIG Template is linked already to the Selected option.

I don’t think it’s a good idea to add each month’s option in the form by hand. Then, create a separate TWIG script for each month and link them together. I prefer to show only those terms which are used in the looper output dynamically. Although the current month may not be included in the current loooper output. Script then needs to pick the next month until we get some output. That sounds rather complex, so probably it is not possible without cusom coding or maybe it is the default behaviour if we use radio option. I just put this idea as the most simple starting point for discussion of a possible solution.

Please let me know if I am thinking in the wrong direction. Maybe there is a simpler way to accomplish it. Or maybe it is currently not possible with what CS and CS Forms have in their toolset.

It seams like there could be an issue with TWIG templates when PHP 8.4 is used on the server.

I also experimented with a background color inside Grid Element. And it turned out that TWIG template is also not working as it should with the Grid Background Color setting.

Here is the output of another TWIG template used within the CS Text Element. It looks like it works as it should inside that element, however the last looper item is not highlighted with the respective global-color inside grid.

This is a confirmation that the template is also linked to the Grid Background Color.

Here is the page with the Grid (the last loop item is marked to be highlited with another background color).

Hey @referee,

The behavior you are experiencing is a classic PHP/Twig interaction issue. Here is a breakdown of why it happens, how to fix it, and how to dynamically select the month.


1. Why it always evaluates to “true”

When you link a Twig template to the Selected option in the builder, Cornerstone processes the template and passes its output string to PHP.

  • If your Twig template outputs true, PHP receives the string "true".
  • If your Twig template outputs false, PHP receives the string "false".
  • If there is any indentation or a newline in your Twig template, PHP receives something like "\n false\n".

In PHP, any non-empty string (except the exact string "0") is considered truthy by !empty(). Thus, !empty("false") evaluates to true, and the option is always marked as selected.


2. How to fix it

To make PHP evaluate the output as false, your Twig template must output absolutely nothing (an empty string "" with no spaces, tabs, or newlines) when the condition is not met.

In Twig, you can strip all surrounding whitespace by using whitespace control tags ({%- and -%}).

Here is the corrected, single-month Twig template that works correctly:

{%- set month = global.date|date('m') -%}
{%- if month == '01' -%}1{%- endif -%}
  • If it’s January: Outputs 1. In PHP, !empty("1") is true (selected).
  • If it’s not January: Outputs absolutely nothing (empty string ""). In PHP, empty("") is true (not selected).

3. Dynamic Twig Script for Loops (Taxonomy Terms)

If you are displaying options dynamically using a Looper Provider (e.g. looping through your Month custom taxonomy terms), you do not need to hardcode each month or create separate Twig scripts.

You can write a single dynamic Twig script to handle all of them. Inside a Cornerstone Looper, you can access the current looped item using looper.item (or term depending on your provider type).

Assuming your taxonomy term slugs are lowercase month names (like january, february, etc.):

{%- set current_month = global.date|date('F')|lower -%}
{%- set term_slug = looper.item.slug | default(term.slug) -%}
{%- if term_slug == current_month -%}1{%- endif -%}

Please just note that the provided codes above are not tested and working with TWIG is custom development. The codes shown above only serve as a guide.

If your taxonomy term slugs are numbers (e.g. 01, 02, 03):

{%- set current_month = global.date|date('m') -%}
{%- set term_slug = looper.item.slug | default(term.slug) -%}
{%- if term_slug == current_month -%}1{%- endif -%}

4. How to Debug Looper Data in Twig

If you are not sure what fields are available on your term looper or what the exact slug format is, you can add a temporary Text element inside the looper item in the builder and output the raw JSON data using:

{{ looper.item | json_encode }}

This will print the exact structure of the looper item on the page so you can verify what keys (like slug, name, or custom taxonomy properties) to use in your comparisons.

1 Like

Thanks again, @christian, for your clear and detailed explanations and guides. That is very valuable for learning and highly appretiated.

Now I can get the term selected based on the current month, which is great. However, it doesn’t make initial filtering by the fact. A click action is still needed after page load beside dynamic term selection to make it happen. And to make it work dynamically on page load we still need to use url.param, I suppose. Then the question is for which purpose Selection option is available in the form element seetings if it doesn’t add the parameter on page load when in Selected state? Is that feature still in development or there is another reason which I do not understand yet? Are the URL parameters that come right after the CPT URL and its slug generated by the CS Form only when users take actions on the page?

I have custom sorting at my archive by one of the ACF fields. To do that I had to use a Query Builder instead of the default archive looper provider. As a consequence I also added this Custom JSON code:

{
    "event-season"  	 : {{ url.param({"key":"event-season"}) | json_encode }},
    "event-month"	     : {{ url.param({"key":"event-month"}) | json_encode }},
    "event-ages"	     : {{ url.param({"key":"event-ages"}) | json_encode }},
    "event-discipline"   : {{ url.param({"key":"event-discipline"}) | json_encode }},
    "event-level"		 : {{ url.param({"key":"event-level"}) | json_encode }},
    "event-country"	     : {{ url.param({"key":"event-country"}) | json_encode }},
    "event-ru"			 : {{ url.param({"key":"event-ru"}) | json_encode }},
    "s" 				 : "{{ url.param({"key":"search"}) }}"
}

Do I need to change something so that the pre-Selected options in my CS Form fields can add the URL parameters to the default URL with a CPT slug right away? Essencially the aim is to filter archive posts immediately when the page is opened.

My second post regarding the background color not changing probably requires another request. I just thought that there could be the same problem which stands behind both cases but apparently it isn’t. Can I expext any suggestion on it here as well or is it better to move it to another thread?