Skip to main content
  1. About
  2. For Teams
Asked
Viewed 3k times
1

UPDATE Was able to make it work, but got one last problem. Updated code is here: VueJs not working on first click or first event

-----------------------------------------------------------

I've been trying to find out a way for the components inside a loop to not act as one.

I have a loop (3 divs), and inside the loop, I have 2 textboxes. But whenever I enter a value in any of them, the value is populated to everyone.

Can anyone help me separate those components?

I'm trying to make the parent div (1st loop) dynamic. So the children components (2nd loop) should be acting separately with their own grandparent components (textbox).

Here's my code:

<div id="app">
    <div v-for="(ctr, c) in 3" :key="c">
      <button @click="input_add">1st</button>
      <div>
        <div v-for="(input, act) in inputs" :key="act.id">
          <input type="text" v-model="input.name"> 
          <input type="text" v-model="input.time">
          <button @click="input_remove(act)">Delete</button>
          <button @click="input_add">Add row</button>
        </div>
      </div>
      {{ inputs }}  
    </div>
  </div>
const app = new Vue({
    el: "#app",
    data: {
    inputs: [],
    counter: 0,
  },

  methods: {
    input_add() {
      this.inputs.push({
        id: this.counter + 1,
        day: null,
        name: null,
        time: null,
      })
      this.counter += 1
    },
    input_remove(index) {
      this.inputs.splice(index,1)
      this.counter -= 1
    }
  }
});

Result:

Result Screenshot

6
  • 1
    try adding a key to the div where you apply the v-for loop like :key="act"
    Troy Kessler
    –  Troy Kessler
    2020-02-04 13:47:32 +00:00
    Commented Feb 4, 2020 at 13:47
  • It's bad practice to have a v-for without a key property (more details : vuejs.org/v2/guide/list.html#Maintaining-State)
    Seblor
    –  Seblor
    2020-02-04 14:41:12 +00:00
    Commented Feb 4, 2020 at 14:41
  • I added a key already after posting this, but that does not solve the problem. (I'll update my post with a key). My problem is the first loop. Loop 1 Loop 2 textbox When you add a textbox in loop 2, of course it will add up to each of element in loop 1. And I need elements in loop 1 to be separate entities. Is it possible?
    Bry
    –  Bry
    2020-02-04 22:16:41 +00:00
    Commented Feb 4, 2020 at 22:16
  • yes, it's because you didn't create a component for the iterated item. you can't prevent this by just applying key...
    yvl
    –  yvl
    2020-02-05 01:06:12 +00:00
    Commented Feb 5, 2020 at 1:06
  • Do you have a proposed solution?
    Bry
    –  Bry
    2020-02-05 01:07:52 +00:00
    Commented Feb 5, 2020 at 1:07

2 Answers 2

1

as I mentioned in the comment, you should create a component for the iterated item.

parent component:

<div v-for="(item, index) in array" :key="index">        
    <child :item="item" />
</div>

Now you sent the item as prop. Let's catch it in child.

child components:

<div>
    <input type="text" v-model="input.name"> 
    <input type="text" v-model="input.time">
    <button @click="input_remove(act)">Delete</button>
    <button @click="input_add">Add row</button>
</div>
{{ inputs }}  

props: [item], // I am not sure you need it or not, BUT just showing how to do it.
data() {return { // your datas };},
methods: {
 // your methods...
},
//and else...

Now each iterated item can control self only. I am hope it make sense now.

then build the buttons an input in child component. After that you can apply the events for just clicked item.

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

5 Comments

Sorry, can you explain further? I'm not familiar with <child>
First create a component, then import it into parent component. then use it as child component inside the div which you applied v-for So, now send the prop like I mentioned in the answer. then get the prop in child. Use it.
I'm getting it now. Instead of including everything inside the loop, just create the data of the parent, then loop the child separately. Thank you!!
No problem. if it solved your problem, then check it as answer for others. @Bry
Hey Tay. I was able to make it work. I just needed to ready the data before iterating. But I have another question, if you're not too busy to check it, here it is: stackoverflow.com/questions/60077788/…
0

You should use Array of Objects. Here's a codesandbox. This way everytime you add a new object to the array, a new index is created with a new name and time ready to be filled in.

<template>
  <div id="app">
    <img width="25%" src="./assets/logo.png">
    <div v-for="item in basic" :key="item.id">
      <button @click="addRow">Add row</button>
      <input type="text" v-model="item.name">
      <input type="text" v-model="item.time">
      {{ item.name }} - {{ item.time }}
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      id: 1,
      basic: [{ name: "", time: "" }]
    };
  },
  methods: {
    addRow() {
      console.log("added");
      this.id += 1;
      this.basic.push({
        name: "",
        time: ""
      });
    }
  }
};
</script>

2 Comments

Thanks! But maybe you oversight my first loop. The problem lies there.
What is 3 referring to then in the first loop, cuz I don't see it in your data. And why would you need it? If the goal is to have dynamic input fields the user can add or destroy, my solution works well. Hope I can help :)

Your Answer

Post as a guest

Required, but never shown

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.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.