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
<script setup lang="ts">
defineProps<{
title: string
theme: string
}>()
</script>
<template>
<div
class="rounded-xl border overflow-hidden transition-colors duration-300"
:class="theme === 'dark'
? 'bg-base-300 border-base-content/20'
: 'bg-base-100 border-base-300'"
>
<!-- Layout header -->
<div
class="px-4 py-3 border-b flex items-center justify-between transition-colors duration-300"
:class="theme === 'dark'
? 'border-base-content/20 bg-base-content/5'
: 'border-base-300 bg-base-200'"
>
<div class="flex items-center gap-2">
<div class="w-2.5 h-2.5 rounded-full bg-error"></div>
<div class="w-2.5 h-2.5 rounded-full bg-warning"></div>
<div class="w-2.5 h-2.5 rounded-full bg-success"></div>
</div>
<span class="text-sm font-medium">{{ title }}</span>
<span class="text-xs px-2 py-0.5 rounded-full bg-secondary/20 text-secondary">
{{ theme }}
</span>
</div>
<!-- Slot for injected page content -->
<div class="p-6">
<slot>
<p class="text-neutral italic text-sm">No page injected</p>
</slot>
</div>
</div>
</template>
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.