79

I have an input text field with a v-model attached, and every time someone hits the "Add" button, another input text gets added to the DOM with the same v-model attached. I thought I'd then get an array of the v-model values, but it only gets the value of the first v-model input:

<div id="app">
  <div id="references">
    <input v-model="references" type="text">
  </div>
  <button @click="addReference">Add</button>
</div>

The html I append to the dom is triggered by the addReference method:

addReference: function(e) {
  e.preventDefault();
  console.log(this.references);
  var inputEl = '<input v-model="references" type="text">';
  $('#references').append(inputEl);
}

Is this something Vue.js can't do? Is there a different approach of gathering values from dynamic dom elements with Vue.js?

new Vue({
  el: "#app",
  data: {
    references: "text"
  },
  methods: {
    addReference: function(e) {
      e.preventDefault();
      console.log(this.references);
      var inputEl = '<input v-model="references" type="text">';
      $('#references').append(inputEl);
    }
  }
})
input {
  display: block;
  margin: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
  <div id="references">
    <input v-model="references" type="text">
  </div>
  <button @click="addReference">Add</button>
</div>

3
  • 15
    Looking back after using Vue for a couple years, at this personal "hello world" Vue question makes me smile, come a long way :D Thanks againd @Bill Criswell Commented Mar 29, 2018 at 12:52
  • 2
    I love to hear that! Sorry I didn't see this sooner. Commented Jan 17, 2019 at 2:08
  • 1
    No problem ^^ Vue makes it so easy to do quite complex things, absolutely loving it still Commented Jan 17, 2019 at 14:46

3 Answers 3

127

You're thinking through DOM, it's a hard as hell habit to break. Vue recommends you approach it data first.

It's kind of hard to tell in your exact situation but I'd probably use a v-for and make an array of finds to push to as I need more.

Here's how I'd set up my instance:

new Vue({
  el: '#app',
  data: {
    finds: []
  },
  methods: {
    addFind: function () {
      this.finds.push({ value: '' });
    }
  }
});

And here's how I'd set up my template:

<div id="app">
  <h1>Finds</h1>
  <div v-for="(find, index) in finds">
    <input v-model="find.value" :key="index">
  </div>
  <button @click="addFind">
    New Find
  </button>
</div>

Although, I'd try to use something besides an index for the key.

Here's a demo of the above: https://jsfiddle.net/crswll/24txy506/9/

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

9 Comments

Aha! So by making finds an array, which allows you to create a v-for, you kind of tell vue it's going to be an array, opposed to expecting v-model single-value to array-value magic of vuejs! Thanks a bunch! Absolutely loving Vuejs.
Actually @Bill Criswell, although this has cleared up some things, it's not really an answer to what I need, so let me try to rephrase. I have an array of references to a find, and when someone adds a find (clicks the + button) a new input field appears that can be filled with another reference. So basically it's a list of references that a user can provide.
That's what the fiddle is doing as far as I can see.
Thanks a lot, thinking too DOM, it's a hard as hell habit to break
When I try this, I get vue.runtime.esm.js?2b0e:1737 TypeError: Cannot read property '_withTask' of undefined
|
31

If you were asking how to do it in vue2 and make options to insert and delete it, please, have a look an js fiddle

new Vue({
  el: '#app',
  data: {
    finds: [] 
  },
  methods: {
    addFind: function () {
      this.finds.push({ value: 'def' });
    },
    deleteFind: function (index) {
      console.log(index);
      console.log(this.finds);
      this.finds.splice(index, 1);
    }
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <h1>Finds</h1>
  <div v-for="(find, index) in finds">
    <input v-model="find.value">
    <button @click="deleteFind(index)">
      delete
    </button>
  </div>
  
  <button @click="addFind">
    New Find
  </button>
  
  <pre>{{ $data }}</pre>
</div>

Comments

14

Here's a demo of the above:https://jsfiddle.net/sajadweb/mjnyLm0q/11

new Vue({
  el: '#app',
  data: {
    users: [{ name: 'sajadweb',email:'[email protected]' }] 
  },
  methods: {
    addUser: function () {
      this.users.push({ name: '',email:'' });
    },
    deleteUser: function (index) {
      console.log(index);
      console.log(this.finds);
      this.users.splice(index, 1);
      if(index===0)
      this.addUser()
    }
  }
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
  <h1>Add user</h1>
  <div v-for="(user, index) in users">
    <input v-model="user.name">
    <input v-model="user.email">
    <button @click="deleteUser(index)">
      delete
    </button>
  </div>
  
  <button @click="addUser">
    New User
  </button>
  
  <pre>{{ $data }}</pre>
</div>

Comments

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.