Ensuring that the desired DOM elements have loaded before attempting to manipulate them in Vue.js

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>

Answer №1

It seems like the issue lies in how you are utilizing it.

Typically, the mounted method is invoked after the component's DOM has been rendered, making this.$el accessible at that point.

However, within the mounted method, you are executing an asynchronous operation that updates the data, and consequently the DOM, upon completion. The problem arises when you attempt to utilize the result before it is available.

The correct approach would be as follows:

mounted() {
  axios.get('/getSight/' + this.placeId)
       .then(response => {
         this.sight = response.data.result.result;
         this.sightImages = response.data.result.result.photos;
         this.$nextTick(() => {
           this.showSlides(this.slideIndex);
         });
       }).catch((error) => console.log(error));
}

Here's a tip: Instead of using el.className += ... or el.className.replace(...), consider employing el.classList.add(...) and el.classList.remove(...).

For more information, refer to the documentation on: Element.classList

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for keeping Fancybox from deleting the selected thumbnail

New to using fancybox and running into some issues.. starting to regret adding it. I have a row of thumbnails, all good, but when I click one it opens the THUMBNAIL instead of the actual link and on top of that, it DELETES the thumbnail from the DOM. I tr ...

Consistently Encountering The 404 Error

Greetings! Below is the code snippet from my app.js: var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require(& ...

React Router relies on a DOM for Browser History to function properly

I am currently developing my app using React.js and express. My main focus right now is setting up react-router-dom for the application. Unfortunately, I encountered a warning when attempting to run the app: Invariant Violation: Browser history needs a ...

Updating Google+ url parameter dynamically without the need to reload the page

Is there a way for a user to share a link on social media platforms like Facebook and Google+ without having to refresh the page? The user can customize the link with an ajax call, ensuring that the page remains static. Here is my code for the Google Plu ...

JavaScript array containing objects remains static

I'm facing an issue with a complex array of objects (I will only display the necessary nodes to explain the problem): var arr = [ { json: { doc: { id: 1, atualizacao:{ ...

"Displaying the y-axis in d3.js: A Step-by-Step

I am a beginner in d3.js and I'm having trouble with my y-axis not showing up in the browser. Can someone please help me find a solution? var barOffset=5; var barWidth=50; var width=700,height=700; function processData(data,key){ var objects=[]; ...

Difficulty with SailsJS Transmitting Information to View Template

I've been trying to establish a connection for hours but haven't had any luck. All I want to do is transfer some data from a controller to a view template. When I navigate the route without specifying a view template, the browser displays the da ...

Stop angular schema form's destroyStrategy from deleting any data

After upgrading my Angular app from version 0.8.2 to 0.8.3 of Angular Schema Form (ASF), a significant bug emerged. The application features multi-page forms that utilize prev/next buttons for navigation. A condition is implemented to display only relevan ...

Is it possible to remove the "disabled" attribute using JS, but the button remains disabled?

There are two buttons on my page: the first one is currently disabled, and the second one is supposed to enable the first button. That's the plan. Button 1: $(document).ready(function() { $('#click').click(function() { document.getE ...

What is the best way to align an image with the position of a div?

Looking for assistance on positioning an image to a div's position after it has been cloned. $(".raindrop1").clone().removeClass("raindrop1").appendTo("body"); $("img").css({"left": "div".x, "top": "div".y}); .shape{ border-radius: 50px; width: 10p ...

Issues arise with the functionality of Datatables when attempting to implement a

I am trying to sort the "Date Created" column in my table in descending order of the latest date. I found a forum that suggested using the datetime datatable sorting plugin, but it didn't work as expected. Can someone help me solve this issue? Below a ...

Regularly updating a book's interactive pages with turn.js technology

I experimented with generating dynamic content in turn.js using the sample provided here. This is an excerpt of the code I have written: <body> <div id="paper"> </div> </body> <script type="text/javascript"> $(win ...

What could be the reason for the Nextjs fetch request returning undefined data?

Here is the code snippet for my GET request in the API section: export default async (req, res) => { const { query: { className }, method } = req; switch (method) { case "GET": try { const classDetail = await Class.findO ...

Is there a way to retrieve two arrays in an Ajax request?

JAVASCRIPT CODE: $.ajax({ url: 'assignavailtrainers.php', data: {action:'test'}, type: 'post', success: function(data) { } }); PHP CODE: <?php $username = "trainerapp"; ...

The Autocomplete feature from the @react-google-maps/api component seems to be malfunctioning as it returns

I'm encountering some difficulties with the Autocomplete component in @react-google-maps/api. While Autocomplete is working and displaying options, clicking on an option fills the input box but I'm only getting 'undefined' from the Plac ...

Sending parameters in SwipeableDrawer in ReactJS using Material UI

This is a demonstration of my SwipeableDrawer from material-ui const sideList = ( </List> <ListItem button component={Link} to="/todos"> <ListItemText primary="Todos" /> </ListItem> </List> ) <SwipeableDrawer o ...

Which is better for privacy: underscored prototype properties or encapsulated variables?

There's something that's been on my mind lately - it seems like people are aware of something that I'm not. Let's take a look at an example in FOSS (simplified below)... When creating a class in JavaScript, I personally prefer Crockford ...

Having trouble with overriding an @media query for material-ui react components?

I've been trying to modify a @media CSS rule on a Material UI component, similar to the discussions on How to over-ride an @media css for a material-ui react component and Override components like MuiTab that use media queries. However, I have not bee ...

Select a checkbox automatically after receiving an ajax response

I am currently working with a form that contains multiple checkboxes like the one below: <label class="checkbox"> <input type="checkbox" id="user_ids_for_edit" name="user_ids_for_edit[]" data-toggle="checkbox" data-toggle="checkbox" value="14"&g ...

The DataType.MultilineText field in my modal popup partial view is causing all validation to fail

I encountered a peculiar issue recently. After creating a new asp.net mvc5 application, I decided to upgrade it to asp.net mvc-5.2.2. The problem arose with the following field:- [Required] [StringLength(200)] public string Name { get; set; } When ren ...