I've been struggling with this issue for the past day and I'm completely stuck. In my vue file, there's a method that operates like this:
methods: {
showSlides(n) {
let slides = document.getElementsByClassName("mySlides");
slides[0].style.display = "block";
}
},
mounted(){
this.showSlides();
}
What it does is find all elements with the class "mySlides," store them in a variable, and then tries to change the style of the first element. This function is triggered when the component is mounted().
The problem arises when I receive an error saying
"TypeError: Cannot read property 'style' of undefined"
. It turns out that at the time this function runs, those DOM elements are indeed undefined. I only realized this when I added a @click='showSlide()'
event to a button. When I click the button, the function executes successfully, but not during mounting.
Coincidentally, the code works perfectly in a plain HTML file where the script sits at the bottom of the page. This discrepancy indicates that something unusual is happening here.
Complete Code:
<template>
<div class="wrapper">
<div class="sight-container">
<p class='sight-name'>{{ sight.name }}</p>
<p>{{ sight.formatted_address }}</p>
<p>{{ sight.formatted_phone_number }}</p>
<p>{{ sight.international_phone_number }}</p>
<p>{{ sight.website }}</p>
<div class="photos-container">
<div v-for='(image, index) in sightImages' class="mySlides">
<div class="numbertext">{{ index + 1 }} / {{ sightImages.length }}</div>
<img class='sight-photos' :src="'https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + '&key='">
</div>
<a class="prev" @click='plusSlides(-1)'>❮</a>
<a class="next" @click='plusSlides(1)'>❯</a>
<div class="caption-container">
<p id="caption"></p>
</div>
<div class="row">
<div v-for='(image, index) in sightImages' class="column">
<img class="demo cursor" :src="'https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + '&key='" style="width:100%" @click="currentSlide(1)">
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return {
placeId: this.$route.params.placeid,
sight: "",
sightImages: [],
slideIndex: 1
}
},
methods: {
showSlides(n) {
let i;
let slides = document.getElementsByClassName("mySlides");
let dots = document.getElementsByClassName("demo");
let captionText = document.getElementById("caption");
if (n > slides.length) {
this.slideIndex = 1
}
if (n < 1) {
this.slideIndex = slides.length
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[this.slideIndex-1].style.display = "block";
dots[this.slideIndex-1].className += " active";
captionText.innerHTML = dots[this.slideIndex-1].alt;
},
plusSlides(n) {
this.showSlides(this.slideIndex += n);
},
currentSlide(n) {
this.showSlides(this.slideIndex = n);
}
},
mounted(){
axios.get('/getSight/' + this.placeId)
.then(response => {
this.sight = response.data.result.result
this.sightImages = response.data.result.result.photos
}).catch((error) => console.log(error));
this.showSlides(this.slideIndex);
}
}
</script>