Phoenix LiveView: Writing a component that takes arbitrary root elements as an argument

2022/08/24

For a while I've been trying to figure out how to write a higher order component in LiveView that allows you to define the root element. While I wouldn't recommend doing this often, there are infrequent scenarios wherein it might be helpful.

One example is when you're writing a higher order component that's acting as a container. You'd like to make the container remain semantic while also keeping the component reusable.

You can use Phoenix.HTML.Tag.content_tag/3 to achieve this.

def button_as(assigns) do
  assigns =
    assigns
    |> assign_extra_attributes([:as])

  ~H"""
  <%= Phoenix.HTML.Tag.content_tag(@as, render_slot(@inner_block), @extra_attributes) %>
  """
end

def some_component(assigns) do
  ~H"""
  <.button_as as={:label}>Label button</.button_as>
  <.button_as as={:button}>Button button</.button_as>
  """
end