Younoch
Younoch

Reputation: 45

Get emit value from specific V-for element

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
          class="w-full"
          :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>

Upvotes: 1

Views: 1057

Answers (1)

tao
tao

Reputation: 90138

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

Upvotes: 2

Related Questions