Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Antonio Orlando's avatar

Passing sharing data between distant components

Hi everyone. I'm using Laravel + vue/inertia and I built a toast notification component. It works with session from laravel's backend data but I'd like to use it to work with data from anywhere. I stored the component in the breeze's authenticated layout component to make sure the notification doesn't disappear if I change pages by clicking on any link. I've tried to use a composable and tried provide/inject to communicate with the notification component but I can't make it to show unless the data comes direct from the session. Here's what I'm trying. Below I'm sharing the code where I'm trying to manually pass the data to the toast component by using provide

<script setup>
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout.vue"
import { Head, useForm } from "@inertiajs/vue3"
import InputError from "@/Components/InputError.vue"
import InputLabel from "@/Components/InputLabel.vue"
import TextInput from "@/Components/TextInput.vue"
import PrimaryButton from "@/Components/PrimaryButton.vue"
import { ref, provide, reactive } from "vue"

const toast = reactive([])

provide("toast", toast)

const form = useForm({
    name: "",
    email: "",
    dob: "",
    street: "",
    zone: "",
    city: "",
    zipcode: "",
})

const placeholderText = ref("")

const fillAddress = async () => {
    if (form.zipcode.length === 8) {
        placeholderText.value = "Buscando resultados..."
        const resp = await axios.get(`https://viacep.com.br/ws/${form.zipcode}/json/`)
        if (resp.data.erro) {
            placeholderText.value = ""

			//this is what I'm trying to share
            toast.push({
                title: "Aviso",
                message: "Nenhum endereço foi retornado, verifique se o seu CEP foi digitado corretamente",
                type: "warning",
            })

        } else {
            placeholderText.value = ""
            form.street = resp.data.logradouro
            form.zone = resp.data.bairro
            form.city = resp.data.localidade
        }
    }
}

Here is the component I'm trying to see if the data is received but it doesn't show anything in the console.log

<script setup>
import ToastListItem from "@/Components/ToastListItem.vue"
import { usePage } from "@inertiajs/vue3"
import { computed, inject } from "vue"
import { useAlert } from "@/Composables/useAlert"

const toast = computed(() => usePage().props.flash.alert)

//expecting data to be injected
const test = inject("toast")

const { alerts, addAlert } = useAlert()

if (toast.value) {
    addAlert(toast.value.title, toast.value.message, toast.value.type)
}

//checking if I could get any data
console.log(test)

I could use a plugin for the notification but I wanted to try and see if I could build something that I could use and learn a bit from my attempt. I really appreciate any help

0 likes
2 replies
LaryAI's avatar
Level 58

To pass data between distant components in Vue 3, you can use the provide and inject functions. In the provided code, the provide function is used to provide the toast object to child components, but the inject function is not used correctly in the ToastListItem component.

Here's how you can fix it:

  1. In the ToastListItem component, use the inject function to inject the toast object:

    const toast = inject("toast")
    
  2. In the fillAddress function, use the addAlert function from the useAlert composable to add the toast message:

    import { useAlert } from "@/Composables/useAlert"
    
    const { addAlert } = useAlert()
    
    // ...
    
    if (resp.data.erro) {
        placeholderText.value = ""
        addAlert("Aviso", "Nenhum endereço foi retornado, verifique se o seu CEP foi digitado corretamente", "warning")
    } else {
        // ...
    }
    

With these changes, the ToastListItem component should receive the toast object and display the toast message correctly.

Here's the updated code:

// AuthenticatedLayout.vue
<template>
  <div>
    <slot />
    <ToastList />
  </div>
</template>

<script setup>
import { reactive, provide } from "vue"
import ToastList from "@/Components/ToastList.vue"

const toast = reactive([])

provide("toast", toast)
</script>

// TextInput.vue
<template>
  <div>
    <input v-model="modelValue" @input="updateValue" />
  </div>
</template>

<script setup>
import { ref, watch } from "vue"

const modelValue = ref(props.value)

watch(
  () => props.value,
  (value) => {
    modelValue.value = value
  }
)

function updateValue(event) {
  props.onUpdate(event.target.value)
}
</script>

// Form.vue
<template>
  <div>
    <TextInput v-model="form.name" />
    <TextInput v-model="form.email" />
    <TextInput v-model="form.dob" />
    <TextInput v-model="form.street" />
    <TextInput v-model="form.zone" />
    <TextInput v-model="form.city" />
    <TextInput v-model="form.zipcode" />
    <button @click="fillAddress">Fill Address</button>
  </div>
</template>

<script setup>
import { useForm } from "@inertiajs/inertia-vue3"
import { ref } from "vue"
import axios from "axios"

const form = useForm({
  name: "",
  email: "",
  dob: "",
  street: "",
  zone: "",
  city: "",
  zipcode: "",
})

const placeholderText = ref("")

function fillAddress() {
  if (form.zipcode.length === 8) {
    placeholderText.value = "Buscando resultados..."
    axios
      .get(`https://viacep.com.br/ws/${form.zipcode}/json/`)
      .then((response) => {
        if (response.data.erro) {
          placeholderText.value = ""
          toast.push({
            title: "Aviso",
            message:
              "Nenhum endereço foi retornado, verifique se o seu CEP foi digitado corretamente",
            type: "warning",
          })
        } else {
          placeholderText.value = ""
          form.street = response.data.logradouro
          form.zone = response.data.bairro
          form.city = response.data.localidade
        }
      })
  }
}
</script>

// ToastList.vue
<template>
  <div>
    <ToastListItem v-for="toastItem in toast" :key="toastItem.id" :toastItem="toastItem" />
  </div>
</template>

<script setup>
import ToastListItem from "@/Components/ToastListItem.vue"
import { usePage } from "@inertiajs/inertia-vue3"
import { computed, inject } from "vue"

const toast = computed(() => usePage().props.flash.alert)

inject("toast", toast)
</script>

// ToastListItem.vue
<template>
  <div>
    <div>{{ toastItem.title }}</div>
    <div>{{ toastItem.message }}</div>
    <div>{{ toastItem.type }}</div>
  </div>
</template>

<script setup>
import { inject } from "vue"

const toast = inject("toast")
</script>
Antonio Orlando's avatar

It seems that I'd get a better response from Lary if I had provided all the code from the components. But the answer gave me some ideas of what to do next. I indeed managed to share the data I was trying to but I need to let the toast component know that there's a new notification and setting up a watcher for this task seems to be the way. I'm gonna tweak my composable and try to make it work with the messages that I manually set

Please or to participate in this conversation.