LiveVue 1.1
Examples v-inject

v-inject

v1.1

Inject a Vue component into another component's slot — even when they're rendered by different LiveViews. The layout component persists while only the page content changes.

What this example shows

1
Layout Component
Rendered with an id, owns the slot
2
Slot Injection
v-inject targets the layout by id
3
Independent Updates
Layout and page update separately
inject_live.ex
defmodule MyAppWeb.InjectLive do
  use MyAppWeb, :live_view

  @messages [
    "Hello from the injected page!",
    "v-inject fills the layout slot",
    "Layout persists across navigation",
    "Only the page content changes"
  ]

  def render(assigns) do
    ~H"""
    <div class="space-y-4">
      <.vue
        id="app-layout"
        v-component="InjectLayout"
        v-socket={@socket}
        title="My App"
        theme={@theme}
      />

      <.vue
        v-component="Inject"
        v-socket={@socket}
        v-inject="app-layout"
        message={@message}
      />

      <div class="flex gap-2">
        <button phx-click="toggle_theme" class="btn btn-sm btn-outline">
          Toggle theme
        </button>
      </div>
    </div>
    """
  end

  def mount(_params, _session, socket) do
    {:ok, assign(socket, theme: "light", message: hd(@messages), message_index: 0)}
  end

  def handle_event("toggle_theme", _params, socket) do
    theme = if socket.assigns.theme == "light", do: "dark", else: "light"
    {:noreply, assign(socket, :theme, theme)}
  end

  def handle_event("change_message", _params, socket) do
    index = rem(socket.assigns.message_index + 1, length(@messages))
    {:noreply, assign(socket, message: Enum.at(@messages, index), message_index: index)}
  end
end

How it works

1 Render a layout component with an id

The layout component is rendered with a unique id. It defines a <slot /> where page content will be injected. In a real app, this would typically live in root.html.heex or a sticky LiveView.

<.vue id="app-layout" v-component="AppLayout" v-socket={@socket} title="My App" />

2 Inject a page into the layout's slot

The page component uses v-inject="app-layout" to target the layout by its id. The page is rendered inside the layout's default slot instead of inline.

<.vue v-component="Page" v-inject="app-layout" v-socket={@socket} message={@message} />

3 Layout and page update independently

Toggle the theme — only the layout re-renders. Change the message — only the page updates. In a real app with a sticky LiveView layout, the layout Vue component persists across LiveView navigation while pages swap in and out of the slot.

Next up: Headless Shared Props
View example →