Add Vuejs models with model.number

Asked

Viewed 180 times

1

I was trying out vuejs and I ran into some difficulties, basically I was adding up 3 inputs and putting the result in a 4th.

Problem, let’s assume I enter:

t.value1 => 1
t.value1 => 0 ( need to delete and put 0 again)
t.value1 => 3

or

t.value1 => 0
t.value1 => 1 ( need to delete and put 0 again)
t.value1 => 3

The total is 13 not 4, vuejs is treating the results as text despite having put the option model.number. I think the cause here is the directive input-noempty which is changing the value of the input directly instead of the model value, but would be the most correct method?

Vue.directive('input-noempty', {
  update: function(el, binding) {
  	// sem zeros a esquerda
    el.value = el.value.replace(/(^|[^0-9])0+/g, "");
    // evita que o campo fique vazio
    el.value = el.value.length == 0 ? 0 : el.value;
  },
});



new Vue({
  el: "#app",
  data: {   
  	t:{
    	valor1:0, valor2: 0, valor3:0, total: function(){return this.valor1 + this.valor2 + this.valor3;}
    }
  }  
})
.total{ border-color: lightblue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">

<input v-input-noempty  type="test" v-model.number="t.valor1" />
<input v-input-noempty  type="test" v-model.number="t.valor2" />
<input v-input-noempty  type="test" v-model.number="t.valor3" />

<input class="total" type="test" v-model.number="t.total()" />

</div>

1 answer

2


From the start one would expect the v-model.number only return numbers, but is not the case... there is a Take on Github on this where one of the team members says that maybe in v.3 this new behavior will be considered. So this is a classic string concatenation problem. You think you’re adding numbers but you’re concatenating strings. Use Number() to convert from string to number and will already work as waits.

I leave an example, slightly modified as suggestion. I use computed because it seems more correct here.

new Vue({
  el: "#app",
  data: {
    t: {
      valor1: 0,
      valor2: 0,
      valor3: 0,
    }
  },
  computed: {
    total() {
      const {valor1, valor2, valor3} = this.t;
      return [valor1, valor2, valor3]
        .map(Number)
        .reduce((input, sum) => input + sum, 0);
    }
  }
})
.total {
  border-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">

  <input v-input-noempty type="test" v-model.number="t.valor1" />
  <input v-input-noempty type="test" v-model.number="t.valor2" />
  <input v-input-noempty type="test" v-model.number="t.valor3" />

  <input class="total" type="test" v-model.number="total" />

</div>

  • Finally I managed to find a solution, I was also forced to use meunumero || 0 and in my case I’m using a component now. After reading about Watchers, directories, Components, at least I’ve learned something new. But he discouraged the vuejs a lot, because he had a table to build, and I thought that vuejs would make my life easier and only delayed me.

  • 1

    @lazyFox made another improvement in the code if you want to use.

Browser other questions tagged

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