Joe Eifert
Joe Eifert

Reputation: 1387

How to use the "with" statement inside an eex template in elixir phoenix

I'd like to run the following code:

<%= with [%{time: time}| _rest] <- day_data do %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% end %>

But that raises (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %{} of type Map.

Then I tried something super simple:

<%= with :foo <- :bar do %>
  <p><%= "eex shouldn't print this" %></p>
<% end %>

And that rendered me "bar" in the template. What? The? actual? bar?

I also tried it without the equal sign, but that didn't include the code in the template.

<% with number <- 1 do %>
  <p><%= "eex does not print this #{number}" %></p>
<% end %>

Can I even use the with statement in eex templates? Or do I have to go with:

<%= if match?([%{time: time}| _rest], day_data) do %>
  <% [%{time: time}| _rest] = day_data %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% end %>

By the way I cannot believe no one has asked this before. I tried to search for an answer. Sorry if it turns out to be a duplicate.

EDIT after the first answer: I also tried (syntax error before: '->'):

<%= with [%{time: time}| _rest] <- day_data do %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% else %>
  <%= _err -> nil %>
<% end %>

No clause (expected -> clauses for :else in "with")

<%= with [%{time: time}| _rest] <- day_data do %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% else %>
<% end %>

And various possible ways to use or not use the equal sign. Also exchanged the nil with an empty string just to be sure.

Upvotes: 3

Views: 585

Answers (1)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Kernel.SpecialForms.with/1 returns the RHO immediately if there is no match.

That said, either you need to handle both possible cases with else or ensure that what’s returned is renderable (as in your case of :foo <- :bar.)

What happens, is <%= attempts to render not matched day_data and fails.


To introduce else one should use the following syntax

<%= with foo <- 42 do %>
  <p><%= MATCH: #{foo} %></p>
<% else _ -> %>
  <p><%= NO MATCH %></p>
<% end %>

Upvotes: 3

Related Questions