Custom Features for Home Assistant Cards - Buttons, Sliders, Selectors, and Spinboxes

Single line templates: you need quotes. If you’re using single quotes on the inside, you need to wrap in double quotes or vice versa, or you must escape your quotes if using only one kind of quote, or use multiline templates without the wrapping quotes. All standard YAML stuff: Thomas Lovén - YAML for Non-programmers.

1 Like

If you use double quotes on the outside it’ll prematurely terminate at the double quotes in sun.sun. You have to use single quotes to wrap the whole thing and double quotes internally or vice versa. You could also use escape character \" quotes but that gets visually messy.

Its funny to see Thomas Loven describe himself as new to Home Assistant in that old article considering he’s created some of the most important custom integrations for it.

Hi, I have one that renders in the developer tools template but not in the label-field, the second one below.

type: grid
cards:
  - features:
      - type: fan-speed
      - type: custom:service-call
        entries:
          - type: button
            icon: mdi:fan
            label: '{{ state_attr("fan.itho_wifi_nrg_xxxx", "fan-speed_rpm") }}'
            unit_of_measurement: rpm
          - type: button
            icon: mdi:fan-auto
            label: '{{ (now()-state_attr("automation.fan_auto_speed","last_triggered")).total_seconds() | timestamp_custom("%H:%M", false) }}'
    type: tile
    entity: fan.itho_wifi_nrg_xxxx
    name: ITHO Fan

This is an unfortunate trade off of how I’ve implemented templating. Instead of using the built in Home Assistant jinja2 templating which sends templates to the backend to process, I’ve implemented it using nunjucks. The pros are that this way templates are processed in the front end and returned on render instantaneously. The cons are that I have to re-implement the Home Assistant template extensions in TypeScript in my ha-nunjucks package. I didn’t reimplement now() and timestamp_custom() since TS/JS and Python handle timestamps very differently, and recreating the behavior of Home Assistant jinja2 template timestamp functions would be very difficult.

Could you try creating a helper template sensor using that template and referencing that in the label template?

I can definitely create a helper sensor to do this and use that.
Thanks for your very speedy replies, appreciated.

1 Like

Hi slightly stuck tonight, I am trying to build the UI for the Dyson Hot and Cold, and new to this integration. I seem to be stuck at the moment getting the percentage on the slider. I can’t see whats wrong. can anyone advise?

type: tile
name: Office
entity: climate.office
icon: mdi:home-thermometer
vertical: false
show_entity_picture: false
features:
  - type: climate-hvac-modes
    hvac_modes:
      - 'off'
      - cool
      - heat
  - type: target-temperature
  - type: custom:service-call
    buttons:
      - service: fan.set_preset_mode
        icon: mdi:fan
        data:
          preset_mode: Normal
          entity_id: fan.office
      - service: fan.set_preset_mode
        icon: mdi:fan-auto
        data:
          preset_mode: Auto
          entity_id: fan.office
  - type: custom:service-call
    entries:
      - type: slider
        service: fan.set_percentage
        value_attribute: percentage
        thumb: default
        label_color: white
        label: ATTRIBUTE[percentage]%
        data:
          entity_id: fan.office
          percentage: VALUE

Where did you find that syntax? You use general HA templating, barring some exceptions.

{{ states('some_entity_with_percentage') }}

or

{{ state_attr('some_entity', 'percentage') }}

Or calculate it in the template, depending on what you have available.

2 Likes

You’re using the old janky string interpolation I removed in v3.0.0. You should now use templates like parautenbach describes.

type: tile
name: Office
entity: climate.office
icon: mdi:home-thermometer
vertical: false
show_entity_picture: false
features:
  - type: climate-hvac-modes
    hvac_modes:
      - 'off'
      - cool
      - heat
  - type: target-temperature
  - type: custom:service-call
    buttons:
      - service: fan.set_preset_mode
        icon: mdi:fan
        data:
          preset_mode: Normal
          entity_id: fan.office
      - service: fan.set_preset_mode
        icon: mdi:fan-auto
        data:
          preset_mode: Auto
          entity_id: fan.office
  - type: custom:service-call
    entries:
      - type: slider
        service: fan.set_percentage
        value_attribute: percentage
        thumb: default
        label: VALUE
        unit_of_measurement: '%'
        style:
          --label-color: white
        data:
          entity_id: fan.office
          percentage: VALUE
2 Likes

Thank you so much, that worked perfect.

Thanks for the reply, I cobbled together the code form this thread.

Is it possible to place the icon and the label horizontally?

With the style options yes. See this example in the README, specifically this bit in the bottom slider style:

style:
  flex-direction: row
icon_style:
  padding: 8px

flex-direction: row makes the icon and label horizontal, and adding padding: 8px to icon style makes it fit nicely within the button borders.

Thanks. I remember, that there is a possibility, but I didn’t find it. Now I see, that it is in Example 3 in the docs. Thanks again.

Is this possible to reverse a the values in slider (left would be the maximum value, right would be the minimum value)? I would like to use it for controlling blinds (see in HA tile card). I know I can reverse with some helper entities but would be nice to do it on UI.

This will reverse the direction of the input range element:

slider_style:
  transform: scaleX(-1)

The caveats being that the colors are reversed and that the tooltip is on the opposite side of where it should be.

I would like to keep the current design (not doing a horizontal flip), I would like to change the underlaying values only.

Nope. This is not possible with HTML input ranges. The best you can do is do the horizontal flip and also switch the background and slider colors.

I thought it is the same control as available in HA tile card. On the top the tilt position slider available natively in HA, and on the bottom created with Service Call Tile Features plugin for the same cover entity:

image

The tilt position is 83% so it is almost opened.

As I see source code of HA version is not a HTML range control. I don’t know how much effort but maybe you should made it possible to use template to transform VALUE before in service call, and maybe a value_template could be added to make the inverse transformation to plot the correct value on the UI.

I thought it is the same control as available in HA tile card.

It’s not. A while ago the Home Assistants developers told custom card developers that we shouldn’t be using Home Assistant custom elements for custom cards since they could implemented breaking changes which would cause our cards to break. Instead of using the built in tile feature custom elements, these ones are recreations that allow for greater user customizability.

I don’t know how much effort but maybe you should made it possible to use template to transform VALUE before in service call

You could try using templating to send the inverse value in the service call data, something like {{ 100 - VALUE }}.

Currently converting all my custom cards including mushroom to Tile + Service Call Tile Features. Combined with card_mod almost anything is possible.

However, I found one use case where I need the value_attribute for a slider to be templatable: a position slider for a media_player entity. Normally you would do this:

type: tile
entity: media_player.slaapkamer
show_entity_picture: true
name: Speaker
state_content:
  - state
  - volume_level
  - app_name
vertical: false
features:
  - type: custom:service-call
    entries:
      - type: slider
        range:
          - 0
          - '{{ state_attr("media_player.slaapkamer", "media_duration") }}'
        step: 1
        value_attribute: media_position
        tap_action:
          action: call-service
          service: media_player.media_seek
          data:
            seek_position: VALUE
        thumb: flat
        style:
          '--color': grey
          height: 20px

However, the media_position attribute only gets updated whenever the state of one the attributes of the entity changes. This is a conscious implementation since otherwise the state machine would be bombarded with updates.

The official approach is to calculate the actual media position on the fly using a template to predict the media position:

{{ 
  state_attr('media_player.slaapkamer','media_position')
  + as_timestamp(now()) 
  - as_timestamp(state_attr('media_player.slaapkamer','media_position_updated_at'))
}}

A suggestion earlier in the thread is to turn the template into a template sensor and use that one, however in the state machine now() only gets triggered once a minute to avoid overloads as well. On the front end this is different, hence why the standard media card as well as the mini media player can show live progress.

Another path could be to tweak the element using card_mod, but the width of the completed portion of the slider is not controlled through CSS but rather an HTML element attribute called value, hence this is not a possible route either.

Any thoughts or suggestions to make this work?

1 Like