krasenyp
You probably already know that <span>{nil}</span> in a HEEX template produces <span> </span> when rendered. I find this very inconvenient because I can’t conditionally display a placeholder content via the :empty CSS pseudo-class, as it doesn’t tolerate whitespace at all. I know, there’s :blank but it’s still experimental and it’s not supported by any browser.
I encountered an article which tries to demonstrate how to check if a slot is empty. The solution falls apart as soon as you call slot_empty? with a slot from a list of slots. The following fragment makes the function report that both slots are not empty while in fact they are.
<.some_component>
<:item></:item>
<:item></:item>
</.some_component>
The following macro is inspired by Phoenix.Component.render_slot/2 and actually renders the slot and checks if it’s all whitespace. If it is, then it returns nil, otherwise - the rendered slot, ready to be put in the template.
defmacro maybe_render_slot(slot, argument \\ nil) do
# This is what `Phoenix.Component.render_slot/2` does with the twist
# that our function can be used outside of a HEEX template.
changed =
if Macro.Env.has_var?(__CALLER__, {:changed, Phoenix.LiveView.Engine}) do
Macro.var(:changed, Phoenix.LiveView.Engine)
end
quote do
rendered =
unquote(changed)
|> Phoenix.Component.__render_slot__(unquote(slot), unquote(argument))
|> Phoenix.HTML.Safe.to_iodata()
blank? =
rendered
# Using Erlang's API because it accepts IO lists and we can avoid
# "materialising" the IO list to a binary. Of course, one can compile
# the regular expression but I skipped it for brevity sake.
|> :re.run("^\s*$")
|> then(&match?({:match, _}, &1))
if not blank? do
Phoenix.HTML.raw(rendered)
end
end
end
Then, in a template, you can use the macro to conditionally render a non-blank slot and use a sibling element as a placeholder content.
<p :for={item <- @items}>
<span :if={rendered = maybe_render_slot(item)}>{rendered}</span>
<span class="hidden only:inline">{@placeholder}</span>
</p>
I hope someone finds this helpful. I can’t wait for the browsers to support the :blank CSS pseudo-class so we don’t need to do such template gymnastics.
Trending in Guides/Tuts
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










