Reputation: 13
I am attempting to pass user id's fetched from an API trough props from parent (App) to child (Modal). The problem is that when I pass the props down to the modal they don't render as they should in the div with the modal-body class, in fact all of them display an id of 1.
App.vue:
<template>
<div class="container mt-3">
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Username</th>
</tr>
</thead>
<tbody v-for="user in users" :key="user.id">
<tr>
<th scope="row">{{ user.id }}</th>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>
<Modal :id="user.id" />
</td>
</tr>
</tbody>
</table>
</div>
<pre>{{ user }}</pre>
</template>
<script>
import axios from "axios";
import Modal from "@/components/Modal.vue";
export default {
name: "App",
components: {
Modal,
},
data() {
return {
users: null,
};
},
methods: {
async load_users() {
try {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
this.users = data;
} catch (error) {
console.log("error");
}
},
},
mounted() {
this.load_users();
},
};
</script>
Modal.vue:
<template>
<!-- Button trigger modal -->
<button
type="button"
class="btn btn-danger"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
>
Delete
</button>
<!-- Modal -->
<div
class="modal fade"
id="exampleModal"
tabindex="-1"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
Are you sure you want to delete user: {{ id }}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Modal",
props: ["id"],
};
</script>
The page preview is the following:
It does not matter on which Delete button I click the id is always 1.
But when I inspect the props in the Vue Devtools they are different, for the second for example it appears 2 as it should:
Any help is appreciated.
Thank you.
Upvotes: 0
Views: 157
Reputation: 943
You are rendering 10 modals each with the same id - exampleModal
, so it's always the first one which is opened. This is why you are experiencing the behaviour you describe.
However - the real problem is with your structure.
Why are you rendering 10 modals? Why not render one and pass in the respective props?
Something like this:
<template>
<Modal v-if="modal.isActive" :id="modal.userId" />
<tbody v-for="user in users" :key="user.id">
<tr>
<th scope="row">{{ user.id }}</th>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>
<button
type="button"
class="btn btn-danger"
@click="onClick(user.id)"
>
Delete
</button>
</td>
</tr>
</tbody>
</template>
<script>
import Modal from '@/components/Modal.vue'
export default {
name: 'App',
components: {
Modal,
},
data() {
return {
users: null,
modal: {
isActive: false,
userId: null,
},
}
},
methods: {
onClick(userId) {
Object.assign(this.modal, { isActive: true, userId })
},
},
}
</script>
Upvotes: 1