Case statement in heex template

I have a bunch of components and a list of data with different “types”. I want to render the appropriate component depending on the type of the data.

This is basically the code i am trying, but i’m not sure the best way to do it with heex.

    for {agg, results} <- @data_list do
      case agg.type do
        "price_stats" -> ~H"""
          <.live_component module={ComponentTestWeb.Components.StatsFacet} id={agg.internal_name} title={agg.title} items={results} />
        """
        _ -> ~H"<.live_component module={ComponentTestWeb.Components.KeywordFacet} id={agg.internal_name} title={agg.title} items={results} />"
      end
    end

How should I do this? I have tried it in the template, but i couldn’t find a good example of case statements in the template. So then i thought i’d do it as a functional component, but it’s not clear to me how to set the assigns correctly. For example, this says i’m doing the wrong thing for change tracking;

  def show_facets(assigns) do
    
    for {agg, results} <- assigns.agg_results do
      case agg.type do
        "price_stats" -> ~H"""
          <.live_component module={ComponentTestWeb.Components.StatsFacet} id={agg.internal_name} title={agg.title} items={results} />
        """
        _ -> ~H"<.live_component module={ComponentTestWeb.Components.KeywordFacet} id={agg.internal_name} title={agg.title} items={results} />"
      end
    end
  end

Maybe like this (not tested)

alias ComponentTestWeb.Components.{StatsFacet, KeywordFacet}
def show_facets(assigns) do
  for {agg, results} <- assigns.agg_results do
    show_agg(agg, results)
  end
end

defp show_agg(%{type: "price_stats"} = agg, results) do
  assigns = %{agg: agg, results: results}
  ~H"""
    <.live_component module={StatsFacet} id={@agg.internal_name} title={@agg.title} items={@results} />
  """
end
defp show_agg(agg, results) do
  assigns = %{agg: agg, results: results}
  ~H"""
    <.live_component module={KeywordFacet} id={@agg.internal_name} title={@agg.title} items={@results} />
  """
end
1 Like

I would do something like this (also untested):

alias ComponentTestWeb.Components.{StatsFacet, KeywordFacet}

def facets(assigns) do
  ~H"""
  <%= for {agg, result} <- @agg_results do %>
    <.agg_result agg={agg} result={result} />
  <% end %>
  """
end

defp agg_result(%{agg: %{type: "price_stats"}} = assigns) do
  ~H"""
  <.live_component module={StatsFacet} id={@agg.internal_name} title={@agg.title} items={@results} />
  """
end

defp agg_result(assigns) do
  ~H"""
  <.live_component module={KeywordFacet} id={@agg.internal_name} title={@agg.title} items={@results}
  """
end
1 Like

I’d just put this 1:1 into heex and be fine. No need to make this more complicated unless it becomes unwieldy.

~H"""
<%= for {agg, results} <- @data_list do %>
  <%= case agg.type do %>
    <% "price_stats" -> %>
      <.live_component module={ComponentTestWeb.Components.StatsFacet} id={agg.internal_name} title={agg.title} items={results} />
    <% _ -> %>
      <.live_component module={ComponentTestWeb.Components.KeywordFacet} id={agg.internal_name} title={agg.title} items={results} />
  <% end %>
<% end %>
"""

If it’s however only the module changing you can also do this:

~H"""
<%= for {agg, results} <- @data_list do %>
    <.live_component module={component_by_type(agg.type)} id={agg.internal_name} title={agg.title} items={results} />
<% end %>
"""

defp component_by_type("price_stats"), do: ComponentTestWeb.Components.StatsFacet
defp component_by_type(_), do: ComponentTestWeb.Components.KeywordFacet
9 Likes