docs icon indicating copy to clipboard operation
docs copied to clipboard

Antlers: handle_prefix docs

Open JohnathonKoster opened this issue 1 year ago • 2 comments

Add documentation for handle_prefix.

The following can be used as a starting point for anyone looking to get it over the finish line (from https://stillat.com/blog/2022/04/22/managing-fieldset-handles-with-antlers-runtime) 🥳


A common design pattern when building Statamic sites is to use fieldsets to create reusable fields across different collections, forms, or pages. Additionally, it is also not uncommon to see specific partials created to display these fieldsets. This is nice since it allows for the same template code and groups of fields to be managed in a central location, and helps to keep things well organized and clean.

As an example, we could have the following fieldset to manage Frequently Asked Questions:

title: FAQ
fields:
  -
    handle: faq
    field:
      collapse: false
      sets:
        questions:
          display: Questions
          fields:
            -
              handle: question
              field:
                input_type: text
                antlers: false
                display: Question
                type: text
                icon: text
                listable: hidden
                instructions_position: above
                read_only: false
            -
              handle: answer
              field:
                antlers: false
                display: Answer
                type: textarea
                icon: textarea
                listable: hidden
                instructions_position: above
                read_only: false
      display: Questions
      type: replicator
      icon: replicator
      listable: hidden
      instructions_position: above
      read_only: false

We could create a partial named components/faq.antlers.html with the following template that would render our fieldset:

<dl>
    {{ faq }}
    <dt>{{ question }}</dt>
    <dd>{{ answer }}</dd>
    {{ /faq }}
</dl>

and simply include the following in other templates when we wanted to reuse our Frequently Asked Questions template:

{{ partial:components/faq  }}

Working with Fieldset Prefixes

The previous example works great when field names do not change. However, because fieldsets can be prefixed, it becomes difficult to create truly reusable partials when targeting fieldsets (or when you may want to render the same group of fields multiple times on the same page, each with a different prefix). Let's assume that the previous fieldset was imported twice within the same blueprint. Once without a prefix, and a second time with the product_ prefix:

title: Home
sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          character_limit: 0
          display: Title
          validate:
            - required
      -
        import: faq
      -
        import: faq
        prefix: product_

Our page would now contain a faq and product_faq variable, each with their own list of Frequently Asked Questions. With this setup, we could either duplicate our partial or simply alias the single variable to render both:

{{ partial:components/faq  }}

{{ partial:components/faq :faq="product_faq" }}

This technique works well when the imported fieldsets are small (such as in this example), but can quickly become tedious if the imported fieldset contains many different fields. This often leads to attempts to writing invalid Antlers code like the following:

{{# Inside `components/faq.antlers.html`. #}}
<dl>
    {{ {prefix}faq }}
    <dt>{{ question }}</dt>
    <dd>{{ answer }}</dd>
    {{ /{prefix}faq }}
</dl>

{{# In another file. #}}
{{ partial:components/faq prefix="product_" }}

Even if the above had worked, it would make handling the non-prefixed case much more difficult. To help with this situation, Antlers Runtime supports the concept of forcing the Runtime to check if a variable exists with any given prefix, before falling back to the normal cascade rules.

Fieldset Prefixes and Variable Names

To have the Runtime check if variables exist with a prefix, you simply need to add the handle_prefix parameter to either the partial tag or the scope tag:

{{ partial:components/faq  }}

{{ partial:components/faq handle_prefix="product_" }}

When the Runtime encounters the handle_prefix parameter, every variable will be checked to see if it exists with a prefix (but only within the partial or scope tag on which it was applied).

When the above code is being evaluated, it would be as if we had written this Antlers instead:

<dl>
    {{ faq }}
    <dt>{{ question }}</dt>
    <dd>{{ answer }}</dd>
    {{ /faq }}
</dl>

<dl>
    {{ product_faq }}
    <dt>{{ question }}</dt>
    <dd>{{ answer }}</dd>
    {{ /product_faq }}
</dl>

The first partial call would render like normal, because no prefix was specified. However, in the second partial call we are specifying the product_ prefix. Because a product_faq variable does exist, that will be used instead of the faq variable (if no prefixed match was found, Antlers will revert back to normal variable Cascade logic).

The scope tag version might look something like this:

{{ scope handle_prefix="product_" }}
<dl>
    {{ faq }}
    <dt>{{ question }}</dt>
    <dd>{{ answer }}</dd>
    {{ /faq }}
</dl>
{{ /scope }}

JohnathonKoster avatar Dec 01 '23 14:12 JohnathonKoster