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:
-
In the
ToastListItemcomponent, use theinjectfunction to inject thetoastobject:const toast = inject("toast") -
In the
fillAddressfunction, use theaddAlertfunction from theuseAlertcomposable 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>