Phoenix 1.6 (available as a release candidate at the time of writing) uses LiveView 0.16, and with it comes a new HTML engine called HEEx. HEEx is HTML-aware, so you will get a compile-time error if your template has errors such as missing closing tags, and it provides a convenient, HTML-like syntax for injecting function components.
One major gotcha with HEEx templates is that you can no longer use the familiar <%= ... %>
interpolation syntax with HTML attributes. E.g where you could previously do this:
<div class="<%= @class %>">...</div>
you will now have to do this instead:
<div class={@class}>...</div>
You can still use the <%= ... %>
syntax for interpolation in the HTML body.
The new syntax is nice and compact, but we ran into difficulties converting a template that uses Alpine.js to HEEx. In that template we have an enabled/disabled toggle button that we animate with Alpine.js. Before converting to HEEx we could provide the initial value of the toggle dynamically using an @enabled assign, like this:
<div x-data="{ enabled: <%= @enabled %>}">...</div>
Unfortunately, a straight translation to the new syntax doesn't work:
<div x-data="{ enabled: {@enabled} }">...</div> # This doesn't work
Workaround
After some unsuccessful experiments with alternative (messy) ways of writing this, we eventually gave up and started looking for a workaround. HEEx lets you set multiple dynamic attributes like this:
<div {@dynamic_attrs}>...</div>
where @dynamic_attrs
is a keyword list or a map containing key/value pairs for the dynamic attributes, e.g [id: "toggle", class: "enabled"]
Using this approach, we did this in our mount
function:
def mount(_params, _session, socket) do
...
{:ok, socket |> assign(dynamic_attrs: [x_data: "{enabled: true}"]
end
In our template we then used the <div {@dynamic_attrs}>...</div>
syntax shown above to get the toggle working.