return null from JS template doesn't work
Checklist
- [X] I updated the card to the latest version available
- [X] I cleared the cache of my browser
Describe the bug While it's not officially stated in the documentation, it has been mentioned somewhere that returning null or undefined from JS template should not change an attribute value. I'm sure it was working this was for long time but recently it stopped working
See example below
Version of the card Version:
To Reproduce This is the configuration I used. It applies unexpected color to the icon (black in my case) instead of yellow/blue for default styles.
type: custom:button-card
entity: binary_sensor.washing_mashine_gui
styles:
icon:
- color: |
[[[
return undefined; // try with null too
]]]
Screenshots N/A
Expected behavior There should be a working way of 'escaping' from JS template without affecting the attribute the template is intended to change.
Desktop (please complete the following information):
- Browser: ANY
Smartphone (please complete the following information):
- Device: iPhoneX
- OS: iOS 15.4.1
- Browser: safari
Additional context N/A
This is returning a black icon because you actively Not set a color, so it reverts to HA default ?
Yes. exactly. I want to set specific color under a specific condition, but otherwise let the system use defaults. Of course, the goal is to not put those default values into JS code (which seems to be doable (but redundant) in case of colors but almost impossible for other CSS attributes)
For example
styles:
icon:
- color: |
[[[
if (something) return red;
else undefined; // return colors set in CSS specific for entity states
]]]
I saw this strategy in your templates (using null). And I believe undefined worked for me too. But now neither of those two work on my end.
in my templates I do use things like:
- border-top: >
[[[
return (entity.state === 'on') ? '0.5rem solid var(--icon-color-on)' : null;
]]]
but there, the null actually means 'dont show a border top'. My advice would be to use a theme color as default in the else clause, so it always reverts to the color you need.
On the binary sensor from your opening post: why not use the core option state_color: true and not customize at all? (not sure if the button_card picks up the state color, so thats why I ask)
you could also try 'none'. It seems to have the same effect in my templates, but, it might just mean 'dont set a specific other color than the default', in stead of 'dont set a color at all'.
Not sure, give it a try.
As long as you dont use none which is then considered a variable, which is not set, so it will result in endless JS template errors in inspector.....
It seems that none and undefined are both just clear values for given CSS attribute. Hence the black color of the icon in my case and no border-top in your example.
IMO none and 'none' are different. For some css styles the none is a valid value, for example display: none. Coincidently if used for other styles which don't accept this value, it may visually appear as expected.
I found in my code working example of that (I guess coincidently because of the same reasons)
styles:
card:
- display: |
[[[ return entity == null ? 'none' : 'undefined' ]]]
state_color: true and not customize at all?
Documentation doesn't mention this attribute. But the point is to override some behavior letting to behave normally when the condition is not met.
There is a state: functionality that allows customizing the card based on its states. But mentioned conditions must not be based on more than the current entity state.
I'm still almost sure I was advised to use undefined but maybe I'm wrong. Anyway it would be useful addition
be careful: when used in a template you need 'none', as I showed above. If you use none without quotes, it is seen as a variable with name none, and that has to be declared first. You'd not want to do that that though, as it is a reserved word.
when used in a card config like display: none, which we do in card_mod also btw, it is not part of a template, and the string none is clear for the interpreter.
see eg:
- animation: >
[[[ return (entity.state > 0) ? 'blink 2s ease infinite' : 'none'; ]]]
you'd write both of these in a state: syntax like:
animation: blink 2s ease infinite
and
animation: none
hope that is helping you?
another nice example, consider this button_card_template:
exist:
styles:
card:
- display: >
[[[ if (!entity) return 'none'; ]]]
works perfectly, notnshowing the card if the entity does not exist. remove the quotes and your in trouble....
the card_mod form for this would be something like:
card_mod:
style: |
:host {
{% if states(config.entity) == 'unknown' %} display: none !important{% endif %}
}
because it is Jinja and the string after the %} is just that, a string, so the interpreter will see it as is.
Thank you for making me aware of none.
However interesting example is this one (from your examples above):
styles:
card:
- display: >
[[[ if (!entity) return 'none'; ]]]
It assumes that if an entity exists some default value is set to display the attribute. IMHO it's not true and it works coincidently only (because setting display to nothing has to promote it to some actual value)
Let me make an analogical example with icon color
styles:
icon:
- color: >
[[[ if (entity.state === undefined) return 'red'; ]]]
In analogy to your snippet, one would expect that if the state is NOT undefined, the icon will get default colors for on and off states.
But it won't - it will be set to black (likely because it sets the color CSS style of this element to empty string) And this is my point on this issue.
I hope a comparison of those two gives a better idea of what is happening and what I want to achieve.