ps-hyp-pt
ps-hyp-pt

Reputation: 15

Vue.js how to replace the text of the button clicked

I my app UI I have a table with a set of permissions listed. In each row there is a toggle-button that sets the default state of each permission to either "deny" or "grant" in the DB.

If the user clicks the button, async action is triggered in the background. It all works perfectly fine, but what I want to add is when user click the button its inner html changes to a spinner or some sort of "wait..." text and the button get disable while the action runs. This is to prevent user from clicking multiple time is the action take a bit longer to complete, giving impression like nothing is happening.

Now, I know how to do it in jQuery or even plain JS, but I have no idea how to access the button properties in VUE.js

My button look like this:

<button @click="defaultPermissionState(perm.id,'grant',$event)">Deny</button>

I'm only recently started into vue.js, so still learning it ;)

UPDATE: I've actually managed to find a way to do it by exploring the $event and being able to change the text and button properties by doing this:

event.path[0].innerHTML = 'wait...';
event.path[0].disabled = true;

but this does not look like a very elegant solution, so if anyone knows of something better I would still like to hear it

Upvotes: 1

Views: 11072

Answers (5)

Vucko
Vucko

Reputation: 20844

You can use v-if with :disabled. Check this quick example:

new Vue({
  el: "#app",
  data: {
    isLoadingArray: []
  },
  methods: {
    clicked(index) {
      this.$set(this.isLoadingArray, index, true)

      setTimeout(() => {
        this.$set(this.isLoadingArray, index, false)
      }, 2000)
    }
  }
})
.lds-dual-ring {
  display: inline-block;
  width: 64px;
  height: 64px;
}

.lds-dual-ring:after {
  content: " ";
  display: block;
  width: 46px;
  height: 46px;
  margin: 1px;
  border-radius: 50%;
  border: 5px solid #fff;
  border-color: #fff transparent #fff transparent;
  animation: lds-dual-ring 1.2s linear infinite;
}

@keyframes lds-dual-ring {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <button type="button" @click="clicked(0)" :disabled="isLoadingArray[0]">
    <div v-if="isLoadingArray[0]" class="lds-dual-ring"></div>
    <span v-else>click me</span>
  </button>

  <button type="button" @click="clicked(1)" :disabled="isLoadingArray[1]">
    <div v-if="isLoadingArray[1]" class="lds-dual-ring"></div>
    <span v-else>click me</span>
  </button>

  <button type="button" @click="clicked(2)" :disabled="isLoadingArray[2]">
    <div v-if="isLoadingArray[2]" class="lds-dual-ring"></div>
    <span v-else>click me</span>
  </button>

</div>

Upvotes: 2

elraphty
elraphty

Reputation: 630

This should help

<template>
   <button disabled={{disableBtn}} 
     @click="defaultPermissionState(perm.id,'grant',$event)">{{btnText}} 
   </button>
</template>

export default {
   data() {
      return {
         btnText: 'Deny',
         disableBtn: false
      }
   },
   method: {
      defaultPermissionState(id, type, e) {
         this.disableBtn = true;
         this.btnText = 'Clicking.....';
      }
   }
}

Upvotes: 1

FiryCode
FiryCode

Reputation: 189

you can use $event to change the inner html for buttons

$event.path[0].innerHTML = "Write the inner html"

Upvotes: 0

Steven Spungin
Steven Spungin

Reputation: 29169

Hide the button and show the spinner using a data or computed property. Update the 'busy' property from your async function.

<button v-if='!busy' @click="defaultPermissionState(perm.id,'grant',$event)">Deny</button>
<spinner v-else />

Upvotes: 0

Prasanna
Prasanna

Reputation: 4656

You can do it like this

data: function() {
   return {
     waiting: false,
     ...otherstuffs
   }
},
methods: {
   callAsync() {
      this.waiting = true;
      callASYNC()
      .then((result) => {
         this.waiting = false;
      })
   }
}

In your HTML

 <button :disabled="waiting"> {{ waiting ? 'Waiting ...' : 'Deny' }} </button>

So basically, just set a flag before you hit the request, and set it back when the call finishes. Use this flag to set the button value to whatever you want

Upvotes: 2

Related Questions