Vuejs: Is it possible to use a condition to enable a @click?

Asked

Viewed 2,145 times

1

I have a disabled button, which depends on other fields to get enabled:

<button class="actAplicarTodosFiltros" disabled="disabled">Aplicar</button>

So I have tabs that make some changes but I wanted the v-on:click these tabs were only executed when the apply button was enabled.

<li v-on:click="executaAlgo"><a href="#">Vendas</a></li>

It is possible to use some v-if from one button to the other?

  • What is the variable that determines whether .actAplicarTodosFiltros is disabled or not?

  • actually are variables determined with jQuery, it getting enabled doesn’t make much difference to me at the moment, I’m looking for something like a v-on:click preventdefault of tabs, and only getting enabled when it gets disabled, I don’t know if I would need a kind of watch

  • "variables determined with jQuery" - leave jQuery! : ) I’m kidding, but if you have logic Vue.js this is much simpler. So you could control both. I’ll give you an example.

  • I’m thinking here and it’s hard to mix jQuery... are different generations and logics. You can show the code that changes the disabled of that button?

  • is simple thing, if on another button that when it is clicked it gives a $('. actAplicarTodosFiltros'). attr('disabled', false);

  • And that part is 100% detached from the Vue component?

  • Aham, disabled is not getting into anything from Vue, only the tabs click

  • Did any of the answers/solved the question?

  • @Sergio they helped yes, but I ended up solving otherwise

  • Ok! It was interesting to put here as an answer to complete the question and solutions

  • @Sergio, I will rephrase the question and put my solution, I think I explained wrong because the solution was simpler than it seemed

Show 7 more comments

3 answers

1

It is possible to mix external code with instances of Vue.js. See the example I did, I created a variable called condicao out of Vue and associated in Vue instance. When you perform this way, the external variable is transformed into two-way databind.

After creating the two-way databind, you can use external functions to manipulate this data, even when it is changed Vue recognizes and changes the component without any problem.

Also create a function to validate the button, on it you disable or enable according to the conditions of the external variable.

Follows code:

var condicao = {
  opcao1: false,
  opcao2: false,
  opcao3: false,
};

function habilitarBotaoComFuncaoExterna() {
  condicao.opcao1 = true;
  condicao.opcao2 = true;
  condicao.opcao3 = true;
}

function desabilitarBotaoComFuncaoExterna() {
  condicao.opcao1 = false;
  condicao.opcao2 = false;
  condicao.opcao3 = false;
}

new Vue({
  el: "#app",
  data: {
    aba: 1,
    condicao: condicao,
  },
  methods: {
    verificaCondicao: function() {
      return !!this.condicao.opcao1 && !!this.condicao.opcao2 && !!this.condicao.opcao3;
    },
    fazAlgumaCoisa: function() {
      console.log('Botão clicado, faz alguma coisa...');
    },
    trocarDeAba: function($event, aba) {
      if (!this.verificaCondicao()) {
        console.log('Habilite opções para prosseguir com a troca de guia.');
        return; // Cancela a ação pois não foi atendida
      }

      // Troca de aba
      this.aba = aba;
    }
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <div>
    <div>
      <a href="#" v-on:click.prevent="trocarDeAba($event, 1)">Aba 1</a>
      <a href="#" v-on:click.prevent="trocarDeAba($event, 2)">Aba 2</a>
      <a href="#" v-on:click.prevent="trocarDeAba($event, 3)">Aba 3</a>
    </div>
    <div>
      <div v-if="aba == 1">Conteúdo Aba 1 ******************</div>
      <div v-if="aba == 2">Conteúdo Aba 2 ------------------</div>
      <div v-if="aba == 3">Conteúdo Aba 3 ##################</div>
    </div>
    <div v-if="verificaCondicao()">
      <h4>Agora você pode clicar nas abas</h4>
    </div>
    <div v-else>
      <h4>Marque as opções para poder alterar de guia</h4>
    </div>
  </div>
  <hr />
  <div>
    <button v-on:click="fazAlgumaCoisa()" class="actAplicarTodosFiltros" :disabled="!verificaCondicao()">
        Opção com Condições
       </button>
  </div>

  <ul>
    <li><input v-model="condicao.opcao1" type="checkbox"> Condição 01</li>
    <li><input v-model="condicao.opcao2" type="checkbox"> Condição 02</li>
    <li><input v-model="condicao.opcao3" type="checkbox"> Condição 03</li>
  </ul>
</div>

<div>
  <button onClick="habilitarBotaoComFuncaoExterna()">Fora do Vuejs - Habilitar</button>
  <button onClick="desabilitarBotaoComFuncaoExterna()">Fora do Vuejs - Habilitar</button>
</div>

  • The problem becomes much simpler with a input that allows bi-directional Binding. The question problem is a property disabled one-button.

  • I changed the example, I think it now fits what he requested. ;)

  • So there is no mistake: I find your answer good, check every time there is click, although you still have no attribute disabled as in the question. My approach is to keep a boolean value in the state component. Both are valid and good answers :P Let’s see what AP prefers :)

  • 1

    Thanks for the comment @Sergio. I left the code with more things to take as an example. One way of not having to check every time, just move the "checkCondicate" to a computed property, so it would have the cache of the same and only in case of exchange of the values that there would be another check. But, the idea was to leave in a simple way, without having to go into every detail of the Vue and the answer become very complex.

1

Mixing jQuery logic with Vue.js is not very simple, and I advise against it. But because it is possible and may even be necessary you can use MutationObserver to detect changes in the button and import them into the Vue. It would be something like this:

document.querySelector('#toggle').addEventListener('click', function toggle() {
  const button = document.querySelector('#app button');
  button.disabled = !button.disabled;
});

new Vue({
  el: '#app',
  data() {
    return {
      disabled: false
    }
  },
  mounted() {
    const button = this.$el.querySelector('button');
    const $this = this;
    new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type == "attributes") {
         $this.disabled = button.disabled;
        }
      });
    }).observe(button, {
      attributes: true
    });
  },
  methods: {
    executaAlgo() {
      if (this.disabled) return;
      alert('Clicado!');
    }
  }
})
p {
  padding: 10px;
  border-radius: 5px;
  border: 1px solid #ccf;
  display: inline-block;
}
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <button class="actAplicarTodosFiltros" :disabled="disabled">Aplicar</button>
  <ul>
    <li v-on:click="executaAlgo"><a href="#">Vendas</a></li>
  </ul>
</div>

<p id="toggle">Clica aqui para desabilitar o botão sem Vue.js</p>

1

The easiest way to do this is by using the directive v-bind.

Example:

<v-bind:disabled="(form.nome == '')">

Browser other questions tagged

You are not signed in. Login or sign up in order to post.