How do you folks use Jinja templates to reuse repetitive YAML?

So I remember seeing a blog post a while back about “Now you can throw jinja templates anywhere in your YAML to generate more YAML.”

Really cool if possible. But so far it hasn’t been possible for me. And I’m ultimately going to need about 40 nearly-identical chunks of about 16 lines, and don’t plan to write out 640 lines myself.

I set up a new dashboard in yaml mode, installed card-mod, config-template-card, and lovelace_gen.
I’ve been trying to do some very basic stuff just so see what I can do.

But for whatever reason, the jinja just does not execute. I’ve tried merging all of this into ui-lovelace.yaml and doing it from there in case it only gets executed in that file alone. But in every case, it just seems to treat it like normal text and lose its mind the moment it sees a %.

It’s funny, too, because I have several template sensors DO import jinja macros. So I’m not sure what I’m missing here. When it doesn’t give me an error about the % sign, It usually just says stuff like “Elements required”. So below is one of probably 50 or versions I’ve made of the same thing with slight modifications each time.

configuration.yaml

lovelace_gen:
lovelace:
  mode: yaml
  dashboards:
    test-view:
      mode: yaml
      title: Tests
      icon: mdi:script
      show_in_sidebar: true
      filename: lovelace/tests.yaml

tests.yaml

resources:
  - url: /local/config-template-card.js
    type: module
title: Tests
views:
- !include views/testview.yaml

testview.yaml

title: Floorplan
resources:
  - url: /local/config-template-card.js
    type: module
cards:
  - type: markdown
    title: Floorplan
    content: >
        Welcome to your **dashboard**.
  - !include dynamic_floorplan.yaml

dynamic_floorplan.yaml

type: 'custom:config-template-card'
entities:
  - light.breakfast
card:
  type: picture-elements
  image: local/backgrounds/wood_black.jpg
  elements:
    - >-
      {% from 'floorplan.jinja' import entity_test %}
      {{ entity_test('light.breakfast') }}

And finally floorplan.jinja inside of custom_templates

{% macro entity_test(entity) -%}
type: state-icon
entity: {{ entity }}
style:
  top: 10%
  left: 70%
{%- endmacro %}

While this is one of several iterations, it is one of the more successful. It basically gives me a card with a background, and then off-screen there’s a box that says something like “entities required”.

But yeah, the thing is that I’m ultimately going to need a macro like this further in my setup. One for each of a couple dozen lights.

{% macro generate_image_block(light_entity, image_path) -%}
    - action: none
        entity: {{ light_entity }}
        hold_action:
          action: none
        image: {{ image_path }}
        style:
          mix-blend-mode: lighten
          filter: >-
            ${ "hue-rotate(" + (states['{{ light_entity }}'].attributes.hs_color[0]) + "deg) saturate(" + (states['{{ light_entity }}'].attributes.hs_color[1]*0.3) + "%) brightness(" + ((states['{{ light_entity }}'].attributes.brightness * 2) - (states['{{ light_entity }}'].attributes.hs_color[1])*2.5) + "%)" }
          top: '-25%'
          left: 0%
          transform: scale(0.75)
        tap_action:
          action: none
        type: image
{%- endmacro %}

For context, the goal is eventually going to be a dynamic floorplan with colored lighting using images rendered via script in unreal engine 5.

Ultimately, unreal engine 5 would get locations from another file that has all the entity locations. So basically you could configure the entity locations, it’ll render each of the light layers automatically, build a picture-elements card with these layers, and then place all the light icons in their respective locations based on that same config file. So if i move lights around or add new lights, it’s basically a matter of setting where the light is, then running a script that pretty much renders and builds everything for me.

It’ll be super awesome if I can get it going. But my struggle is just in creating reusable, auto-generated code chunks in yaml.

I can tell you exactly how I would accomplish this in C, C++, C#, Java, Python, and Javascript. If I could switch to those for the UI and forget about YAML and Jinja, I totally would. (preferably not html/css until the very end. it blows my mind that css doesn’t have basic color multiplication or basic color addition.)

You can’t template the config itself with Jinja — only values of keys. What you want to do require the use of YAML anchors and includes.

This might help (scroll to the end): Thomas Lovén - YAML for Non-programmers.

Haha. Well that explains a lot. Thanks!

I’ve used &anchors and !includes before. My understanding is that anchors can’t be passed into includes.

So might there be a way to pass parameters into includes? I’ve seen something that looks something like this:

element:
  - !include:
    - lighttemplate.yaml
      entity: light.breakfast
      image: light.breakfast.png

And then you’re able to pass “parameter” into the include, which might look like:

type: image
entity: {{ entity }}
image: {{ image }}
style:
<etc>

But it seems like I hadn’t gotten that to work, either. It appears to pass the parameters as jinja, and the jinja templates are being used in the included file, but then it tells me “{{entity}}” is an invalid entity. So it doesn’t seem to execute jinja there, either. Perhaps because it’s nested.

Just getting an idea of what I can and can’t do now.

I’m running into the same question with several dashboards containing columns of very similar cards. I’d be curious to hear what solutions you may have settled on if they are applicable to the specific case of similar cards inside the same dashboard (which is defined via YAML).

I found this related discussion therapeutic after all my struggles to eliminate/avoid pages and pages of redundant code: (1) Stupid question: Why use YAML and not an actual programming language for automations? : homeassistant (reddit.com)

I solved this with a custom button card where i create a template and pass the values in as variables.