LiveVue
1.1
v-inject
v1.1Inject 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
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.