Join loop iterations: joiner
The joiner template function creates a small helper object for joining items in a loop with a separator. When you call the joiner, it returns an empty string the first time and the separator string on every subsequent call. This avoids the common problem of getting a leading or trailing separator when building a delimited string in a loop.
This provides an alternative to the join filter when you need more control over how items are separated. For example, if you are conditionally including items in a loop, the join filter may not work cleanly because it operates on a full list. A joiner only emits the separator between items that are actually rendered.
Usage
Here’s how to use this template function. Copy any example and adjust it to your setup.
{% set sep = joiner(", ") %}
{% for item in ["apple", "banana", "cherry"] %}
{{ sep() }}{{ item }}
{% endfor %}
apple, banana, cherry
Function signature
The signature is a technical summary of this template function. It shows the name of the function, the values (called parameters) it accepts, and what type of data each parameter expects (for example, a piece of text or a number).
Function parameters that have a = with a value after them are optional. If you leave them out, the default value shown is used automatically. Function parameters without a default are required.
joiner(
separator: str = ", ",
) -> Joiner
Function parameters
The following parameters can be provided to this function.
Good to know
- The first call returns an empty string, so you can place it before each item without worrying about a leading separator.
- The default separator is
", "with a trailing space. - A fresh
joiner()must be created per loop. Reusing one across loops keeps counting from where it left off.
Try it yourself
Ready to test this? Open Developer tools > Template, paste the example into the Template editor, and watch the result update on the right. Edit the values to see how the function adapts to your own entitiesAn entity represents a sensor, actor, or function in Home Assistant. Entities are used to monitor physical properties or to control other entities. An entity is usually part of a device or a service. [Learn more].
More examples
Real scenarios where this function comes up in automations and templates. Copy any example and adapt it to your setup.
Conditionally join active sensors
Build a string of only the sensors that are on, properly separated.
{% set sep = joiner(" | ") %}
{% for entity in ["binary_sensor.front_door", "binary_sensor.back_door",
"binary_sensor.garage"] %}
{% if is_state(entity, "on") %}
{{ sep() }}{{ state_attr(entity, "friendly_name") }}
{% endif %}
{% endfor %}
Front Door | Garage
Still stuck?
The Home Assistant community is quick to help: join Discord for real-time chat, post on the community forum with your template and expected result, or share on our subreddit /r/homeassistant.
AI assistants like ChatGPT or Claude can also explain or fix templates when you describe what you want in plain language.
Related template functions
These functions work well alongside this one:
-
Cycle through values: cycler - Creates an object that cycles through a list of values. Useful for alternating between values in a loop.
-
Generate a number sequence: range - Generates a sequence of numbers, like Python’s range(). Commonly used for looping a specific number of times.