Home > Enterprise >  Get emit value from specific V-for element
Get emit value from specific V-for element

Time:03-19

I'm trying to get ID from specific element. But the data is returning as many elements as there are and all are same value. Even if I click another element button, the value was unchanged.The output Screenshot How I resolve this?

Here parent component code:

<template>
        <ProductsList
          
          :product="item"
          @product-id="selectedID"
          v-for="(item, idx) in products"
          :key="idx"
        />
</template>
<script>
export default {
  async asyncData(context) {
    const products = await context.app
      .$axios({
        method: "get",
        url: process.env.PROJECT_API   "/products",
        headers: {
          Authorization: `Bearer ${context.store.state.currentToken}`,
        },
      })
      .then((res) => res.data.products);
    return {
      products,
    };
  },
  methods: {
    selectedID(id) {
      this.products.find( el => {
        el._id === id
        console.log({id});
      })
    }
  },
}
</script>

The child component code:

<template> 
 <button @click="passId">
   details
 <button>
<template> 

export default {
    props: ['product'],
    methods: {
      passId() {
        this.$emit('product-id', this.product._id)
      }
    },
}
</script>

CodePudding user response:

Your selectedID method assigns the searched id to every product.

find() returns the first item for which the checked condition is true.
Your find() doesn't check anything. Instead, it assigns the id to each element (you're using = instead of ===), without returning anything, which technically means it returns undefined, which evaluates to false for each item. So your .find() doesn't find anything.

In other words, you have to replace

selectedID(id) {
  this.products.find( el => {
    el._id = id
    console.log({id});
  })
}

with:

selectedID(id) {
  console.log(this.products.find(el => el._id === id)?._id);
}

or, more explicitly:

selectedID(id) {
  const product = this.products.find(el => el._id === id);
  if (product) {
    console.log(product._id);
  }
}

In the above find, el => el._id === id is shorthand for:

function(el) {
  return el._id === id;
}

Read more about arrow functions.


Working example:

Vue.component('product-item', {
  template: `<button @click="passId">details</button>`,
  props: ['product'],
  methods: {
    passId() {
      this.$emit('select-product', this.product._id);
    }
  }
});

new Vue({
  el: '#app',
  data: () => ({
    products: [
      { _id: 'one' },
      { _id: 'two' },
      { _id: 'three' }
    ]
  }),
  methods: {
    selectProduct(id) {
      console.log(this.products.find(p => p._id === id)?._id);
    }
  }
})
button {
  display: block;
  cursor: pointer;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app">
  <product-item
    v-for="product in products"
    :key="product._id"
    :product="product"
    @select-product="selectProduct" />
</div>

In the example above I changed a couple of names:

  • <ProductsList> => <ProductItem>
  • selectedID => selectProduct
  • Related