In my vue.js application there items can be removed.
The div element looks like this:
<div class="ride-delete" @click="delete">
<p>Delete</p>
</div>
This is the method that handles the click
:
methods: {
delete ()
{
swal({
title: "Weet u het zeker?",
text: "Het is niet mogelijk deze handeling te herstellen!",
cancelButtonText: 'Stop',
type: "error",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Ja, verwijder deze rit.",
closeOnConfirm: false
}, () => {
RideService.destroy(this.ride)
.then(() => {
swal({
title: "Rit succesvol verwijderd",
type: "success",
showCancelButton: false,
timer: 2000,
showConfirmButton: false
});
this.$router.go('/administratie/ritten');
});
});
}
}
So how can I make sure that if the user clicks 3 times fast after each other there will only be send one request. Right now there are send 3. So the button should be disabled if the user clicks once on it.
--EDIT--
import swal from 'sweetalert';
import RideService from '../../services/RideService';
export default {
data () {
return {
ride: { user: {}, location: {}, type: {} },
deleting: false
}
},
route: {
data ({ to }) {
return RideService.show(this.$route.params.rideId)
.then(function(data)
{
this.ride = data.data.ride;
}.bind(this));
}
},
methods: {
remove ()
{
if (!this.deleting) {
this.deleting = true
swal({
title: "Weet u het zeker?",
text: "Het is niet mogelijk deze handeling te herstellen!",
cancelButtonText: 'Stop',
type: "error",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Ja, verwijder deze rit.",
closeOnConfirm: false
}, () => {
RideService.destroy(this.ride)
.then(() => {
swal({
title: "Rit succesvol verwijderd",
type: "success",
showCancelButton: false,
timer: 2000,
showConfirmButton: false
});
this.deleting = false
this.$router.go('/administratie/ritten');
});
});
this.deleting = false
}
}
}
}
</script>
--EDIT 2--
<template>
<div class="row center">
<div class="panel ride">
<div class="ride-title bar-underline">
<div class="ride-item-title">
<strong class="ride-item-title-body">Rit van {{ ride.created_at }}</strong>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Naam</p>
</div>
<div class="ride-item-content">
<p>{{ ride.user.name }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Locatie van</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.from }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Locatie naar</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.from }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Beschrijving</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.description }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Kmz</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.kmz }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>kmp</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.kmp }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Uren</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.hour }} uur</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Google maps</p>
</div>
<div class="ride-item-content">
<p>{{ ride.location.maps }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Datum</p>
</div>
<div class="ride-item-content">
<p>{{ ride.created_at }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Tijd</p>
</div>
<div class="ride-item-content">
<p>{{ ride.time }}</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Factureerbare tijd</p>
</div>
<div class="ride-item-content">
<p>{{ ride.billabletime }} uur</p>
</div>
</div>
<div class="ride-item bar-underline">
<div class="ride-item-title">
<p>Type</p>
</div>
<div class="ride-item-content">
<p>{{ ride.type.name }}</p>
</div>
</div>
<div class="ride-item">
<div class="ride-edit">
<p>Edit</p>
</div>
<div class="ride-delete" @click="remove">
<p>Delete</p>
</div>
</div>
</div>
</div>
</template>
<script>
import swal from 'sweetalert';
import RideService from '../../services/RideService';
export default {
data () {
return {
ride: { user: {}, location: {}, type: {} },
processing: false
}
},
route: {
data ({ to }) {
return RideService.show(this.$route.params.rideId)
.then(function(data)
{
this.ride = data.data.ride;
}.bind(this));
}
},
methods: {
remove ()
{
if (this.processing === true) {
return;
}
this.processing = true
swal({
title: "Weet u het zeker?",
text: "Het is niet mogelijk deze handeling te herstellen!",
cancelButtonText: 'Stop',
type: "error",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Ja, verwijder deze rit.",
closeOnConfirm: false
}, () => {
RideService.destroy(this.ride)
.then(() => {
swal({
title: "Rit succesvol verwijderd",
type: "success",
showCancelButton: false,
timer: 2000,
showConfirmButton: false
});
this.processing = false
this.$router.go('/administratie/ritten');
});
});
this.processing = false
}
}
}
</script>
Since Vue 2.1.4, there's a really simple solution to this:
Change:
<div class="ride-delete" @click="delete">
<p>Delete</p>
</div>
To:
<div class="ride-delete" @click.once="delete">
<p>Delete</p>
</div>
@click.once
only runs the target method one time.
In my case, it solved a problem with login, where multiple clicks would append path chunks to the URL, like this: localhost:8000/admin/oms/admin/oms/admin/oms
.
Here the description in the official Vue documentation: https://vuejs.org/v2/guide/events.html#Event-Modifiers
I'd suggest storing the state of the async request in a data property (e.g. processing: false and when the user clicks on the element, set it to true), and then within the delete() method check the state to continue or stop the code. Finally, reset the state in success/failure handlers.
For instance:
new Vue({
el: '#app',
data: {
processing: false
},
methods: {
delete(el) {
// terminate the function
// if an async request is processing
if (this.processing === true) {
return;
}
// set the async state
this.processing = true;
var paragraphs = Array.from(this.$el.querySelectorAll('p'));
// simulating the async request
setTimeout(() => {
if (paragraphs.length) {
paragraphs.shift().remove();
}
// on success or failure
// reset the state
this.processing = false;
}, 3000);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<div id="app">
Processing: {{ processing }} <br>
<button @click.prevent="delete()">
Click here to delete a paragraph
</button>
<p v-for="1 in 3">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis officia adipisci, omnis cum odit modi perspiciatis aliquam voluptatum consectetur. Recusandae nobis quam quisquam magnam blanditiis et quos beatae quasi quia!
</p>
Try this
<div class="ride-delete" v-show="!deleting" @click="delete">
<p>Delete</p>
</div>
methods: {
delete ()
{
if (!this.deleting) {
this.deleting = true
swal({
title: "Weet u het zeker?",
text: "Het is niet mogelijk deze handeling te herstellen!",
cancelButtonText: 'Stop',
type: "error",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Ja, verwijder deze rit.",
closeOnConfirm: false
}, () => {
RideService.destroy(this.ride)
.then(() => {
swal({
title: "Rit succesvol verwijderd",
type: "success",
showCancelButton: false,
timer: 2000,
showConfirmButton: false
});
this.deleting = false;
this.$router.go('/administratie/ritten');
});
});
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With