Reputation: 115
I'm new to Vuejs. I have written a vuejs component for delete confirmation modal. I call this inside a list of records, here is my code :
<template id="bs-modal">
<div class="modal fade" id="confirmDeleteModal" tabindex="-1"
role="dialog" aria-labelledby="confirmDeleteModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title"
id="confirmDeleteModalLabel">
Delete {{ item | capitalize }}
</h4>
</div>
<div class="modal-body">
Are you sure about deleting the {{ name }} {{ item }} ?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary"
v-on:click="deleteItem(id)">Yes</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
}
},
props: ['item', 'name', 'id'],
methods: {
deleteItem : function(id) {
var url = window.location.href;
var baseUrl = url.substring(0,
url.indexOf('/', url.indexOf('://') + 3) + 1);
var adminPosition = url.indexOf('admin/') + 6;
var entity = url.substring(adminPosition,
url.indexOf('/', adminPosition));
this.$http.delete(baseUrl + "admin/" + entity + "/" + id).then((response) => {
if (response.body.status_code == '200') {
// Calling just modal('hide') does not hide the backdrop
// There should be a better solution for this
$("#confirmDeleteModal").modal("hide");
$("#confirmDeleteModal").hide();
$('.modal-backdrop').hide();
$("body").removeClass("modal-open");
$("tr[data-id=" + id + "]").remove();
// Display success message
}
});
}
},
filters: {
capitalize: function (value) {
if (!value) {
return '';
}
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
}
</script>
And here is my blade template where I call this component (I'm using laravel 5.3) :
@foreach ($categories as $category)
<tr data-id="{{ $category->id }}">
<td>{{ $category->id }}</td>
<td>{{ $category->name }}</td>
<td id="actions">
<a href="{{ url('admin/category/' . $category->id . '/get') }}">Show</a>
<a href="{{ url('admin/category/' . $category->id . '/edit') }}">Edit</a>
<a href="#" data-toggle="modal" data-target="#confirmDeleteModal">Delete</a>
<confirm-delete-modal item="category" id="{{ $category->id }}" name="{{ $category->name }}"></confirm-delete-modal>
</td>
</tr>
@endforeach
The parameters I pass to the component are variable and according to Vue devtools, the component gets the correct value for each record but when I run the code, it always gets the parameters of first record in list.
Am I missing something ?
Upvotes: 3
Views: 1717
Reputation: 73609
You need to use v-bind when passing variables as props, like following"
<confirm-delete-modal item="category" v-bind:id="{{ $category->id }}" v-bind:name="{{ $category->name }}"></confirm-delete-modal>
or in short you can replace v-bind
with :
as:
<confirm-delete-modal item="category" :id="{{ $category->id }}" :name="{{ $category->name }}"></confirm-delete-modal>
Upvotes: 0
Reputation: 140
I think the main issue came from same Id for all components and when you click on a link first element with ID (confirmDeleteModal) will be opened.
You can set an unique id for each components like this:
<div class="modal fade" :id="'confirmDeleteModal_'+id" tabindex="-1"
role="dialog" aria-labelledby="confirmDeleteModalLabel">
Upvotes: 1
Reputation: 115
I think calling the confirm-delete-modal for each record is a wrong method. I moved the modal outside the loop and made some changes to the code to solve the problem :
Here is the code of confirmDelete.vue :
<template id="modal-template">
<transition name="confirm-delete-modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
Are you sure about deleting the {{ this.$parent.item_name }} {{ item }} ?
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<button class="modal-default-button" @click="deleteItem();">
Yes
</button>
<button class="modal-default-button" @click="$emit('close')">
No
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
data () {
return {
}
},
props: ['item'],
methods: {
deleteItem : function() {
var url = window.location.href;
var baseUrl = url.substring(0, url.indexOf('/', url.indexOf('://') + 3) + 1);
var adminPosition = url.indexOf('admin/') + 6;
var entity = url.substring(adminPosition, url.indexOf('/', adminPosition));
this.$http.delete(baseUrl + "admin/" + entity + "/" + this.$parent.item_id).then((response) => {
if (response.body.status_code == '200') {
$("tr[data-id=" + this.$parent.item_id + "]").remove();
this.$emit('close');
// Display success message
}
});
}
},
filters: {
capitalize: function (value) {
if (!value) {
return '';
}
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
}
</script>
And here is the blade template :
@foreach ($categories as $category)
<tr data-id="{{ $category->id }}">
<td>{{ $category->id }}</td>
<td>{{ $category->name }}</td>
<td id="actions">
<a href="{{ url('admin/category/' . $category->id . '/get') }}">Show</a>
<a href="{{ url('admin/category/' . $category->id . '/edit') }}">Edit</a>
<a href="#" id="{{ $category->name }}_{{ $category->id }}" @click="setDeleteModal($event)">Delete</a>
</td>
</tr>
@endforeach
<confirm-delete-modal item="category"
v-if="showDeleteModal"
@close="closeDeleteModal">
<h3 slot="header">Delete Category</h3>
</confirm-delete-modal>
And finally here is the code of parent vue instance :
new Vue({
el: '#crud',
data: {
showDeleteModal: false,
item_id: '',
item_name: ''
},
methods: {
setDeleteModal: function(e) {
this.showDeleteModal = true;
params = e.target.id.split("_");
this.item_id = params[1];
this.item_name = params[0];
},
closeDeleteModal: function() {
this.showDeleteModal = false;
}
}
});
I hope this helps someone else.
I'll be glad to know the idea of experts in vuejs.
Upvotes: 0