i have a problem to handle dynamic props in vue with typescript, here is my parent component
<script setup lang="ts">
const friends = [
{
id: "emanuel",
name: "Emanuella e",
phone: "08788",
email: "emanuella@gmail.com",
isFavorite: true,
},
{
id: "denta",
name: "Denta W",
phone: "08789",
email: "denta@gmail.com",
isFavorite: false,
},
];
function toggleFavorite(friendId:any){
console.log(friendId);
const identifiedFriend= friends.find(friend=>friend.id === friendId);
if(identifiedFriend!=undefined){
identifiedFriend.isFavorite=!identifiedFriend.isFavorite
}
console.log(identifiedFriend);
}
</script>
<template>
<section>
<header><h1>Test Friends</h1></header>
<ul>
<friend-container
v-for="friend in friends"
:id="friend.id"
:key="friend.id"
:name="friend.name"
:phone="friend.phone"
:email="friend.email"
:isFavorite="friend.isFavorite"
@toggle-favorite="toggleFavorite"
>
</friend-container>
</ul>
</section>
</template>
and here is my child component
<template>
<li>
<h2>{{ name }} {{ isFavorite ? "(Favorite)" : "" }}</h2>
<button @click="toggleFavorite">Toggle Favorite</button>
<button @click="toggleDetails">Show details</button>
<ul v-if="detailAreVisible">
<li><strong>Phone: </strong>{{ phone }}</li>
<li><strong>email: </strong>{{ email }}</li>
</ul>
</li>
</template>
<script setup lang="ts">
import { ref} from 'vue';
const detailAreVisible=ref(false);
const props = defineProps<{
id: { type: String; required: true };
name: { type: String; required: true };
phone: { type: String; required: true };
email: { type: String; required: true };
isFavorite: Boolean
}>();
const emit=defineEmits<{
(e: 'toggle-favorite', value: any): void
}>()
function toggleDetails(){
detailAreVisible.value=!detailAreVisible.value
}
function toggleFavorite(){
emit("toggle-favorite",props.id);
}
</script>
i already change the props data in parent component using emit event handling, but in my child component, isFavorite value still cant change, am i miss something or how to handle it? sorry im new in vue
>Solution :
The state friends should be declared with reactive in order to respond to the changes, and you should also reduce the attributes binding by using only v-bind with multiple attributes since the prop names are the same as state keys :
<script setup lang="ts">
import {reactive} from 'vue'
const friends = reactive([
{
id: "emanuel",
name: "Emanuella e",
phone: "08788",
email: "emanuella@gmail.com",
isFavorite: true,
},
{
id: "denta",
name: "Denta W",
phone: "08789",
email: "denta@gmail.com",
isFavorite: false,
},
]);
function toggleFavorite(friendId:any){
console.log(friendId);
const identifiedFriend= friends.find(friend=>friend.id === friendId);
if(identifiedFriend != undefined){
identifiedFriend.isFavorite = !identifiedFriend.isFavorite
}
console.log(identifiedFriend);
}
</script>
<template>
<section>
<header><h1>Test Friends</h1></header>
<ul>
<friend-container
v-for="friend in friends"
:key="friend.id"
v-bind="friend"
@toggle-favorite="toggleFavorite"
>
</friend-container>
</ul>
</section>
</template>