I have 3 components: TaskList, TaskItem and TaskForm.
The TaskList contains a loop to render all data in TaskItem. Each TaskItem have a edit buttom, that i want to open a TaskForm (modal using bootstrap) with the task data.
TaskForm.vue
<div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" id="formModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="staticBackdropLabel">{{ props.task.name }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
</div>
</div>
</div>
TaskList.vue
<div class="container">
<TaskItem
v-for="task in props.tasks"
:key="task.uuid"
:task="task"
/>
</div>
TaskItem.vue
<div class="row align-items-center p-2 border rounded mt-2">
<div class="col-3">
{{ props.task.name }}
</div>
<button class="btn btn-primary" @click="showForm = !showForm" data-bs-toggle="modal" data-bs-target="#formModal">
<i class="bi bi-pencil-square"></i>
</button>
</div>
<TaskForm v-if="showForm" :task="props.task"/>
But when i do it like this, in every modal, i get the first task name, instead of the selected one.
I don't think this is the best way to do what I want to do in the end (edit a list item), but it's the one I came up with. If someone has a better proposal, I will be happy to read it.
I would recommend using the TaskForm component only once, this can be achieved using props and emits like this
// for parent component
<template>
<ChildComponent v-for="item in items" key={item.id} :item="item" @edit-item="showEditModal" />
<PopUpComponent v-if="selectedItem !== null" :selected-item="selectedItem" @close="selectedItem = null" />
</template>
<script setup>
import {ref} from "vue";
const selectedItem = ref(null);
function showEditModal(item) {
selectedItem.value = item;
}
</script>
For child component we need to define an emit named edit-item that will call this function
// for child
<template>
..other data
<button @click="editItem">edit</button>
</template>
<script setup>
const emit = defineEmits(["edit-item"]);
function editItem() {
emit('edit-item', props.item) // this will call the @edit-item in parent and that function will set a selectedItem non-null value which will render the modal
}
</script>
Similarly for a close function in modal
<template>
...
<button @click="closeModal">close</button>
</template>
<script setup>
const emit = defineEmits(["close"])
function closeModal() {
emit("close")
}
</script>