Migrating templates from 0.15.x to 0.17.9.
Any ideas on how to conditionally render an element attribute?
Before I could simply do it as shown below, but it doesn’t work anymore:
<div <%= if @foo do %> my-attribute<% end %>>
</div>
Migrating templates from 0.15.x to 0.17.9.
Any ideas on how to conditionally render an element attribute?
Before I could simply do it as shown below, but it doesn’t work anymore:
<div <%= if @foo do %> my-attribute<% end %>>
</div>
Try:
<div my-attribute={@foo}>
</div>
Falsy values (nil, false) will not show my-attribute
on the element, true
will render my-attribute
Thanks, but are you sure it won’t be rendered if falsy? Asking because I have plenty of templates to migrate and a non trivial amount of JS depending on such attributes.
Also, is this documented anywhere (haven’t found it in the guides)? If not, it should be.
are you sure it won’t be rendered if falsy?
Positive. The new HEEx syntax uses {}
to interpolate values over <%= %>
<div data-my-attr={false}></div>
Will render like:
<div></div>
You can also do string interpolation for things like conditionally adding classes:
<div class={"px-4 #{if some_condition, do: "py-4"}"}></div>
If some_condition
is true, you’ll get:
<div class="px-4 py-4"></div>
If false/nil, you’ll get:
<div class="px-4 "></div>
Thanks a lot!
You can also do something like this:
<div class={["px-4", some_condition && "py-4" ]}>
Did not know this - Much cleaner!
This is VERY interesting. Can you please point out where this is documented. I wonder if there’s more to it.
To rephrase: does the interpolation behave exactly like string interpolation but with change tracking?
Playing with examples now. Just noticed that the rendered output varies based on the attribute it is being defined for. For example:
<div class={ [ "foo", "bar"]}></div>
renders into
<div class="foo bar"></div>
(with a space character added between the two class names)
While:
<div something-else={ [ "foo", "bar"]}></div>
renders into:
<div something-else= "foobar"></div>
Again, will really appreciate if there are in-depth docs on this. Thanks.
Only class
has that behavior:
The following attribute values have special meaning:
true
- if a value istrue
, the attribute is rendered with no value at all. For example,<input required={true}>
is the same as<input required>
;
false
ornil
- if a value isfalse
ornil
, the attribute is not rendered;
list
(only for theclass
attribute) - each element of the list is processed as a different class.nil
andfalse
elements are discarded.
Read more here:
Thanks!
Don’t understand why they chose to document this under sigil_H function as it applies to templates regardless of how their rendering is invoked (i.e. may as well be implicit), but it’s good to know where it is and that this is all to it.
The docs link is no longer valid. I found equivalent on:
https://hexdocs.pm/phoenix_live_view/0.20.17/Phoenix.Component.html#sigil_H/2
But then the docs say:
false
ornil
- if a value isfalse
ornil
, the attribute is omitted. Some attributes may be rendered with an empty value, for optimization purposes, if it has the same effect as omitting. For example,<checkbox checked={false}>
renders to<checkbox>
while,<div class={false}>
renders to<div class="">
;
while in fact it seems to render <div class>
instead.
What I am looking for though is a way do completely omit the class attribute, despite the “optimization purposes” (whatever they are) Any clues?
If the class
attribute is rendered even if set to false
or nil
as such, I guess it’s an oversight.
I double-checked and it renders class=""
indeed. It was browser’s devtools “elements” that displayed it as class
alone. Thus at least this part behaves as mentioned in the docs but what if I don’t want the “optimization” and just want to get
<div id="advanced">
from
<div id="advanced" class={unless @advanced_show, do: "hidden"}>
It doesn’t have to be exactly as the second line above but you get the idea. Any simple way to achieve this?
I wouldn’t expect there to be an opt out of the optimization or it would be mentioned there. However I’d argue that whatever reason you have to need the class to be omitted instead of empty might be better off pushed to not be communicated via the existance of the class attribute.
Yes, you are right. And – TBH – I wouldn’t allow myself to depend on something “brittle” like the presence of the class attribute for an important piece of logic. It’s more of “can I easily get what I want?”. If I can’t that’s not the end of the world either. At least it doesn’t render class
alone as I initially thought it did.