10

I'm using vue-2.4 and element-ui 1.4.1.

Situation

I have a basic input which is linked with v-model to a computed property. When blur I check if the value input is greater or lower than min and max and I do what I have to do ... Nothing fancy here.

Problem

The value displayed in the input does not always equal enteredValue

Steps to reproduce

1) Input 60 --> Value displayed is the max so 50 and enteredValue is 50 (which is ok)

enter image description here

2) Click outside

3) Input 80 --> Value displayed is 80 and enteredValue is 50

enter image description here

Questions

How can I fix that so the value displayed is always the same as the enteredValue ?

Here is the minimal code to reproduce what I'm facing JSFIDDLE

    <div id="app">
  The variable enteredValue is {{enteredValue}}
  <el-input v-model="measurementValueDisplay" @blur="formatInput($event)"></el-input>
</div>

var Main = {
  data() {
    return {
      enteredValue: '',
      max: 50,
      min: 10
    }
  },
  computed: {
      measurementValueDisplay: {
          get: function () {
              return this.enteredValue + ' inchs'
          },
          set: function (newValue) {
          }
     },
  },
  methods: {
      formatInput($event) {
         let inputValue = $event.currentTarget.value;
         if (inputValue > this.max) { this.enteredValue = this.max}
         else if (inputValue < this.min) { this.enteredValue = this.min}
         else this.enteredValue = inputValue
      }
  }
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
Léo Coco
  • 4,022
  • 11
  • 52
  • 97

3 Answers3

7

Reading this vuejs, will understand what happens

"computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed."

Changed some comportament of the code. Made run: computed() method not works properly for update value in window. But if looks at console the value yes updated. So, i remove computed (getter and setter), and put into data, without setter and getter( i dont like this in javascript).

var Main = {
  data() {
    return {
      measurementValueDisplay:'fff',
      enteredValue: '',
      max: 50,
      min: 10
    }
  },
  computed: {
      /*measurementValueDisplay: {
          get: function () {
              console.log('Computed was triggered so I assume enteredValue changed',this.enteredValue);
              return this.enteredValue + ' inchs'
          },
          set: function (newValue) {
          console.log('setter de qye', this.enteredValue);
          }
      },*/
  },
  methods: {
      formatInput($event) {
          this.enteredValue = 0;
          
          let inputValue = $event.currentTarget.value;
          console.log(inputValue);
          if (inputValue > this.max) { this.enteredValue = this.max}
          else if (inputValue < this.min) { this.enteredValue = this.min}
          else this.enteredValue = inputValue
          this.measurementValueDisplay = this.enteredValue + ' inchs'
          
          console.log(this.enteredValue, 'oioioioio0');
      }
   }
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
tony19
  • 125,647
  • 18
  • 229
  • 307
Álvaro Touzón
  • 1,247
  • 1
  • 8
  • 21
2

Your problem is that the values used in the computed property was not updated with the validation capping at 50 (Was 50, is now updated to 50, no need to recalculate), therefore v-model did not update the input.

I've edited your jsfiddle to use two computed properties:
One with an accessor to validate the entered value, one which returns the value with " inch" appended.

Here is the interesting part:

    computed: {
          measurementValueDisplay: {
              get: function () {
                  return this.enteredValue
              },
              set: function (newValue) {
                 this.enteredValue = 0;
                 let inputValue = parseInt(newValue);
                 if(Number.isNaN(inputValue)){this.enteredValue = this.min}
                 else if (inputValue > this.max) { this.enteredValue = this.max}
                 else if (inputValue < this.min) { this.enteredValue = this.min}
                 else this.enteredValue = inputValue
              }
         },
         valueWithInch(){
            return this.enteredValue + " inch";
             }
      },

nart
  • 1,508
  • 2
  • 11
  • 24
Antony
  • 1,253
  • 11
  • 19
  • I like it but try to enter 500000 by keeping the 0 down. You would be able to get 50000 in the box and 50 as the value – Léo Coco Aug 02 '17 at 15:58
  • You're right, this is the same problem as previously I'll mess a bit with the code to find a better solution – Antony Aug 02 '17 at 16:13
1

In case anybody still needs a hack for this one, you can use a value that will always change ( for example a timestamp )

var Main = {
  data() {
    return {
      enteredValue: '',
      max: 50,
      min: 10,
      now: 1 //line added
    }
  },
  computed: {
      measurementValueDisplay: {
          get: function () {
              return (this.now - this.now + 1 ) * this.enteredValue + ' inchs'; //line changed
          },
          set: function (newValue) {
              this.now = Date.now(); //line added
          }
     },
  },
  methods: {
      formatInput($event) {
         let inputValue = $event.currentTarget.value;
         if (inputValue > this.max) { this.enteredValue = this.max}
         else if (inputValue < this.min) { this.enteredValue = this.min}
         else this.enteredValue = inputValue
      }
  }
}
Lucian Filote
  • 21
  • 1
  • 4