Search code examples
javascriptvue.jsvuejs2watchv-model

How to store formatted data in Array in Vue, watch and v-model aren't saving formatted data?


I have multiple text boxes and when the user types in different text boxes, I want to have an array that stores all this formatted data.

The formatted data is in m:ss (m - minute, s - seconds)

Right now, all the different text boxes show the same value, because there is only one this.formatTime.

How do we change this so that v-model goes through the array, and adds it into an array of formatted values?

The textbox should show the formatted value and store it in allFormatValues[].

I'm really stuck on this, thanks for your time!

<div id="app">
   <div
      v-for="(input, index) in valueInputs"
      :key="index"
    >
     <input
         v-model="formatTime" //want to use allFormatValues[index], instead
         id="time-input"      //but this loses the formatting if I change to 
                              //above
         type="text"
     />
  </div>
</div>

And

 watch: {
   formatTime () {
      const totalLength = this.formatTime.length;
      let a = this.formatTime.replace(/[^0-9]/g, "")
        .substr(0, 1);

      const b = this.formatTime.replace(/[^0-5]/g, "")
        .substr(1, 1);

      const c = this.formatTime.replace(/[^0-9]/g, "")
        .substr(2, 1);
      if (totalLength >= 2) {
        a = `${a.substring(0, 1)}:${b}${c}`;
      }
      this.formatTime = a;
    },
}

I have an array I want to loop through and set this value

data () {
  return {
  valueInputs: [],    // a list of inputs
  allFormatValues: [] // want to store all the formatted values here by the index
 }
}

Solution

  • You could bind the <input>'s value to the iterator, and add an input-event handler that calls formatTime() to update valueInputs:

    1. Bind <input>.value to the input variable:

      <input :value="input" ...>
      
    2. On the <input>, add an input-event handler that receives the iterator index and the event value:

      <input @input="formatTime(index, $event.target.value)" ...>
      
    3. Update the formatTime() method to receive the index and $event.target.value arguments. Also use vm.$set() to reactively update valueInputs[index] with the new value:

      export default {
        methods: {
          formatTime(index, input) {
            const totalLength = input.length;
            let a = input.replace(/[^0-9]/g, "").substr(0, 1);
      
            //...
      
            this.$set(this.valueInputs, index, a)
          }
        }
      }
      

    demo