[Vuejs]-Change content on page on clicking a vue js child element

0👍

Option1: change the child component

Instead of creating a component only just for one feature button, I would embed the whole list of features in a component with h1 where you want to show the selected feature. So, the child component will look like this:

<template>
  <div>
    <li v-for="(feature, key, index) in features" :key="index">
      <button @click="setFeature(feature)">
        <img :src="require('../assets/images/' + feature.item.img)" />
      </button>
    </li>
    <h1>{{ clickedFeuatureText }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
        clickedFeuatureText:null
    }
  },
  methods: {
    setFeature(e){
      this.clickedFeuatureText = e.item.text
    }
  },
  props: {
    features: Array
  }
}
</script>

And here is the parent component with corresponding changes:

<template>
  <div>
    <div v-for="product in getProduct(productId)" :key="product.productId">
      {{ product }}
      <Halo
        :featuresCount="
          `circle-container-` + product.features.length.toString()
        "
      >
        <Feature :features=" product.features"></Feature>
      </Halo>
    </div>
  </div>
</template>

<script>
import Halo from '@/components/ProductHalo.vue'
import Feature from '@/components/ProductFeature.vue'
import json from '@/json/data.json'

export default {
  name: 'ProductSingle',
  components: {
    Halo,
    Feature
  },
  data() {
    return {
      products: json
    }
  },
  computed: {
    productId() {
      return this.$route.params.id
    }
  },
  methods: {
    getProduct(id) {
      let data = this.products
      return data.filter(item => item.productId == id)
    }
  }
}
</script>

Option2: create the new component for one product

Another way is to leave a child component as is, but create the new component representing one product in the list:

<template>
  <div>
      {{ product }}
      <Halo
        :featuresCount="
          `circle-container-` + product.features.length.toString()
        "
      >
        <Feature
          v-for="(feature, key, index) in product.features"
          :key="index"
          :feature="feature"
          @changeProductData="setFeatureText"
        ></Feature>
      </Halo>

      <h1>{{ clickedFeature}}</h1>

    </div>
  </div>
</template>

<script>
import Feature from '@/components/ProductFeature.vue'
import Halo from '@/components/ProductHalo.vue'

export default {
  name: 'product',
  components: {
    Feature,
    Halo 
  },
  data () {
    return {
      clickedFeature: null
    }
  },
  props: {
    product: Object
  },
  methods: {
    setFeatureText(e) {
      this.clickedFeature = e.item.text
    }
  }
}
</script>

Then use the new Product component:

<template>
  <div>
    <product 
      v-for="product in getProduct(productId)" 
      :key="product.productId" 
      :product="product"
    ></product>
  </div>
</template>

<script>
import Product from '@/components/Product.vue'
import json from '@/json/data.json'

export default {
  name: 'ProductSingle',
  components: {
    Product
  },
  data() {
    return {
      products: json
    }
  },
  computed: {
    productId() {
      return this.$route.params.id
    }
  },
  methods: {
    getProduct(id) {
      let data = this.products
      return data.filter(item => item.productId == id)
    }
  }
}
</script>

Leave a comment