3

Currently, I have a VueJS app where you can click a button to create a set of two inputs. These two inputs perform a simple math function on key up. These math functions work with one set of inputs. However, since I'm using document.getElementById to grab the inputs, it will only work on the first set of inputs. Is there any way I can uniquely identify each set of inputs so I can perform this math function individually?

Example:

Vue.component('product', {
  template: `
    <div>
      <select>
        <option>Product One</option>
        <option>Product Two</option>
      </select>
      <input class="input" id="bags" @keyup="$emit('calculatevolume')" type="number" placeholder="Bags">
      <input class="input" id="volume" @keyup="$emit('calculatebags')" type="number" placeholder="Volume">
      <button @click="$emit('remove')">Delete</button>
    </div>
  `
})
new Vue({
  el: '#app',
  data: {
    index: 0,
    products: []
  },
  methods: {
    addProduct: function() {
      this.products.push(this.index);
      this.index++;
    },
    calculatevolume: function() {
      var inputs = document.querySelectorAll(".input");
      var bags = document.getElementById("bags");
      var volume = document.getElementById("volume");
      volume.value = bags.value * 25;
    },
    calculatebags: function() {
      var inputs = document.querySelectorAll(".input");
      var bags = document.getElementById("bags");
      var volume = document.getElementById("volume");
      bags.value = volume.value / 25;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>

<div id="app">
  <button
         v-model="index"
         v-on:click="addProduct"
         placeholder="Add Product">Add Product</button>

  <div class="products">
    <div
         is="product"
         v-for="(product, index) in products"
         :id="index"
         :key="product"
         @remove="products.splice(index, 1)"
         @calculatevolume="calculatevolume"
         @calculatebags="calculatebags">
    </div>
  </div>
</div>

2
  • Why don't you use v-model on your input fields instead? Commented Apr 11, 2017 at 20:39
  • I just read that in the documentation. Definitely looks like a step in the right direction. I also don't think I'm supposed to grab elements by their id, let alone create the same variables twice for two different methods. That was more for testing purposes as I couldn't get global variables to work. Commented Apr 11, 2017 at 20:43

1 Answer 1

5

With Vue, you generally do not want or need to be manipulating the DOM yourself in any way.

To that end, I moved the calculation of bags and volume into your component. Using v-model, they will always reflect the value in data. Additionally, I added watchers to their values so you could change the opposite number when they change.

Vue.component('product', {
  template: `
    <div>
      <select>
        <option>Product One</option>
        <option>Product Two</option>
      </select>
      <input class="input" id="bags" v-model="bags" type="number" placeholder="Bags">
      <input class="input" id="volume" v-model="volume" type="number" placeholder="Volume">
      <button @click="$emit('remove')">Delete</button>
    </div>
  `,
  data(){
    return {
      bags: null,
      volume: null
    }
  },
  watch:{
    bags(newVal){
      this.volume = newVal * 25
    },
    volume(newVal){
      this.bags = newVal / 25
    }
  }
})

new Vue({
  el: '#app',
  data: {
    products: []
  },
  methods: {
    addProduct: function() {
      this.products.push(this.index);
    },
  }
})

And the new template

<div id="app">
  <button
         v-on:click="addProduct"
         placeholder="Add Product">Add Product</button>

  <div class="products">
    <div
         is="product"
         v-for="(product, index) in products"
         :id="index"
         :key="product"
         @remove="products.splice(index, 1)"
         >
    </div>
  </div>
</div>

Example.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the quick response. I agree, it felt wrong to manipulate the DOM since that's the whole point of the directives. I'm still getting acquainted with Vue but your solution really did help for what I ended up using the select element for. Greatly appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.