LiveVue 1.0
Examples Event Handling

Event Handling

Two ways to send events from Vue to LiveView: Phoenix bindings like phx-click and programmatic pushEvent() via the useLiveVue() hook.

What this example shows

1
phx-click
Phoenix bindings in Vue
2
pushEvent()
Programmatic events
3
useLiveVue()
Access Phoenix hook
Events.vue
<script setup lang="ts">
import { ref } from "vue"
import { useLiveVue } from "live_vue"

type Message = { id: number; text: string; from: string }

const props = defineProps<{ messages: Message[] }>()

const inputText = ref("")
const live = useLiveVue()

function sendWithPushEvent() {
  if (!inputText.value.trim()) return
  live.pushEvent("add_message", { text: inputText.value })
  inputText.value = ""
}
</script>

<template>
  <div class="card bg-base-200 p-6 space-y-6">
    <div class="space-y-3">
      <div class="text-sm font-medium text-neutral">Send event with pushEvent()</div>
      <div class="flex gap-2">
        <input
          v-model="inputText"
          type="text"
          placeholder="Type a message..."
          class="input input-bordered flex-1"
          @keyup.enter="sendWithPushEvent"
        />
        <button @click="sendWithPushEvent" class="btn btn-primary">
          Send
        </button>
      </div>
    </div>

    <div class="space-y-3">
      <div class="text-sm font-medium text-neutral">Send event with phx-click</div>
      <div class="flex gap-2 flex-wrap">
        <button
          phx-click="phx_click_message"
          phx-value-text="Hello!"
          class="btn btn-outline"
        >
          Say Hello
        </button>
        <button
          phx-click="phx_click_message"
          phx-value-text="LiveVue rocks!"
          class="btn btn-outline"
        >
          LiveVue rocks!
        </button>
        <button phx-click="clear" class="btn btn-ghost text-neutral">
          Clear
        </button>
      </div>
    </div>

    <div class="space-y-3">
      <div class="flex items-center justify-between">
        <div class="text-sm font-medium text-neutral">Messages from server</div>
        <div class="text-xs text-neutral/50">{{ props.messages.length }} total</div>
      </div>
      <div class="min-h-[120px] p-4 rounded-lg bg-base-300 border border-base-300">
        <div v-if="props.messages.length === 0" class="text-neutral/50 text-sm text-center py-6">
          No messages yet. Send one above!
        </div>
        <div v-else class="space-y-2">
          <div
            v-for="msg in props.messages"
            :key="msg.id"
            class="flex items-center gap-3 text-sm"
          >
            <span
              :class="[
                'badge font-mono',
                msg.from === 'pushEvent'
                  ? 'badge-primary badge-outline'
                  : 'badge-secondary badge-outline'
              ]"
            >
              {{ msg.from }}
            </span>
            <span>{{ msg.text }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

How it works

1 Phoenix bindings work directly in Vue

Standard Phoenix event bindings like phx-click work in Vue templates. Pass data with phx-value-* attributes.

<button phx-click="phx_click_message" phx-value-text="Hello!">

2 useLiveVue() provides the Phoenix hook

The useLiveVue() composable returns the Phoenix LiveView hook instance. Use it for programmatic event handling.

const live = useLiveVue()

3 pushEvent() sends data to LiveView

Call pushEvent(name, payload) to send events programmatically. This is useful when you need to send computed values or handle complex interactions.

live.pushEvent("add_message", { text: inputText.value })

4 handle_event receives both event types

LiveView handles events from both phx-click and pushEvent() the same way. The params contain the payload you sent.

def handle_event("add_message", %{"text" => text}, socket)
Next up: Server Events with useLiveEvent()
View example →