0
votes

How can I fix this error "Computed property "main_image" was assigned to but it has no setter"?

I'm trying to switch main_image every 5s (random). This is my code, check created method and setInterval.

<template>
  <div class="main-image">
    <img v-bind:src="main_image">
  </div>
  <div class="image-list>
    <div v-for="img in images" class="item"><img src="img.image"></div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'Item',
  data () {
    return {
      item: [],
      images: [],
    }
  },
  methods: {
    fetchImages() {
      axios.get(`/api/item/${this.$route.params.id}/${this.$route.params.attribute}/images/`)
      .then(response => {
          this.images = response.data
      })
      .catch(e => {
          this.images = []
          this.errors.push(e)
      })
    },
  },
  computed: {
    main_image() {
      if (typeof this.item[this.$route.params.attribute] !== 'undefined') {
        return this.item[this.$route.params.attribute].image_url
      }
    },
  },
  watch: {
    '$route' (to, from) {
      this.fetchImages()
    }
  },
  created () {
    axios.get(`/api/item/${this.$route.params.id}/`)
      .then(response => {
          this.item = response.data
      })
      .catch(e => {
          this.errors.push(e)
      })
      this.fetchImages();
      self = this
      setInterval(function(){ 
        self.main_image = self.images[Math.floor(Math.random()*self.images.length)].image;
      }, 5000);
  }, 
}
</script>
1
Can you explain what you'd like to happen and when? What should main_image be before the AJAX request completes? What should it be immediately after and then what should it be every 5 seconds?Phil
@Phil befere AJAX request from fetchImages it should be this.item.main_image and then every 5s should iterate over this.images from fetchImages and change v-bind:src="main_image" to next element(next image)Florovit

1 Answers

0
votes

Looks like you want the following to happen...

  1. main_image is initially null / undefined
  2. After the request to /api/item/${this.$route.params.id}/ completes, it should be this.item[this.$route.params.attribute].image_url (if it exists)
  3. After the request to /api/item/${this.$route.params.id}/${this.$route.params.attribute}/images/ completes, it should randomly pick one of the response images every 5 seconds.

I'd forget about using a computed property as that is clearly not what you want. Instead, try this

data() {
  return {
    item: [],
    images: [],
    main_image: '',
    intervalId: null
  }
},
methods: {
  fetchImages() {
    return axios.get(...)...
  }
},
created () {
  axios.get(`/api/item/${this.$route.params.id}/`).then(res => {
    this.item = res.data
    this.main_image = this.item[this.$route.params.attribute] && this.item[this.$route.params.attribute].image_url
    this.fetchImages().then(() => {
      this.intervalId = setInterval(() => {
        this.main_image = this.images[Math.floor(Math.random()*this.images.length)].image;
      })
    })
  }).catch(...)
},
beforeDestroy () {
  clearInterval(this.intervalId) // very important
}