Esteban Vargas
Esteban Vargas

Reputation: 594

How to temporarily disable conditionally rendered buttons in Vue JS?

I have 2 groups of conditionally rendered buttons.

When a campaign is running enter image description here

When a campaign isn't running enter image description here

What I want to do is disable the play button after the campaign has been paused for 5 seconds.

This is my markup:

<div class='m1 '>

  <md-button v-on:click='changeCampaignStatus(campaign.id, "Paused")' v-if='campaign.state==="Running"' class='md-icon-button md-accent md-raised' id='run-button'>
    <md-icon>pause</md-icon>
  </md-button>

  <md-button v-on:click='changeCampaignStatus(campaign.id, "Running")' v-if='campaign.state==="Paused"' class='md-icon-button md-accent md-raised' id='run-button'>
    <md-icon>play_arrow</md-icon>
  </md-button>

  <md-button v-on:click='changeCampaignStatus(campaign.id, "Canceled")' v-if='campaign.state==="Paused"' class='md-icon-button md-accent md-raised' id='run-button'>
    <md-icon>stop</md-icon>
  </md-button>

  <md-button v-on:click='deleteCampaign(campaign.id)' v-if='campaign.state==="Canceled"' class='md-icon-button md-accent md-raised' id='run-button'>
    <md-icon>delete_forever</md-icon>
  </md-button>

  <md-button v-on:click='duplicateCampaign(campaign.id)' class='md-icon-button md-accent md-raised'>
    <md-icon>content_copy</md-icon>
  </md-button>

  <md-button v-on:click='goToEdit'  v-if='campaign.state==="Paused"' class='md-icon-button md-accent md-raised'>
    <md-icon>mode_edit</md-icon>
  </md-button>
  <div>
    <md-chip v-for='tag in campaign.tags' :key='tag' class='mr1'>{{tag}}</md-chip>
  </div>
</div>

I'm not exactly sure which buttons should have the id='run-button', I believe the conditional rendering is making the following setTimeout behave strangely:

  document.getElementById("run-button").disabled = false;
  setTimeout(function(){document.getElementById("run-button").disabled = true;},5000);

With this logic I can get the button to be initially enabled and be disabled after 5 seconds, but if I switch the booleans (first line true, second line false) it somehow just messes up everything. Why is this happening?

How can I implement this correctly?

Upvotes: 3

Views: 3607

Answers (1)

acdcjunior
acdcjunior

Reputation: 135832

Don't mix Vue and direct DOM manipulation.

Optimal solution here is to create a property that will tell if it has been pause by more than 5 seconds, and add such property to :disabled.

For instance,

data() {
  return {
    // ...
    pausedFor5Seconds: false,
    // ...
  };
},
// ...
methods: {
  // ...
  pause() {
    // some mutation that sets campaign.state to "Paused"
    this.pausedFor5Seconds = false;
    setTimeout(() => this.pausedFor5Seconds = true, 5000);
  },
  play() {
    // some mutation that sets campaign.state to "Running"
    this.pausedFor5Seconds = false;
  }
}

Being pause and play, as the comments say, the methods where you mutate the campaign.state.

And in your template add :disabled="pausedFor5Seconds":

<md-button v-on:click='changeCampaignStatus(campaign.id, "Running")'
  v-if='campaign.state==="Paused"' class='md-icon-button md-accent md-raised'
  :disabled="pausedFor5Seconds">
    <md-icon>play_arrow</md-icon>
</md-button>

And the id is not even necessary anymore (which, by the way, you have multiple elements with the same run-button id -- that's invalid HTML and messes up your document.getElementById()s).

Upvotes: 5

Related Questions