Issue with rendering data in VueJS child component

I have created a screen with tabs to organize different data sections, and each tab is meant to be its own component.

However, I am facing an issue where the data does not display on the component when it initially renders. Oddly enough, clicking the refresh button makes the data load perfectly fine. There are no error messages being shown, so I suspect there might be a misunderstanding of the VueJS lifecycle on my part.

const CommentScreen = {
      props: {
        accountid: {
            type: Number,
            required: true
        }
    },
    template: `
        <div>
            <CommentForm
                v-on:commentsupdated="comments_get"
                v-bind:accountid="accountid"
            ></CommentForm>
            <v-btn round color="primary" v-on:click="comments_get" dark>Refresh Comments</v-btn>
            <v-data-table
                :headers="commentheaders"
                :items="comments"
                hide-actions>
                    <template slot="items" slot-scope="props">
                        <td>{{ props.item.entrydate }}</td>
                        <td>{{ props.item.entryuserforename + " " + props.item.entryusersurname }}</td>
                        <td>{{ props.item.comment }}</td>
                    </template>
            </v-data-table>
        </div>
    `,
    components: {
        'CommentForm': CommentForm
    },
    data(){
        return {
            commentheaders:[
                { text:'Entry Date', value:'entrydate' },
                { text:'Entry User', value:'entryuserforename' },
                { text:'Comment', value:'comment' }
            ],
            comments:[]
        }
    }
    ,
    mounted() {
        this.comments_get();
    },
    methods:{
        comments_get(){
            let url = new URL('/comments/', document.location);
            url.searchParams.append('accountid',this.accountid);

            let options = {
            method: 'GET',
            mode: 'cors',
            headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json;charset=UTF-8'
                }
            };

            self = this;
            fetch(url, options)
                .then(
                    response => {
                        if (response.status === 401) {
                            self.$root.$emit('notloggedin');
                        } else if (response.status === 403) {
                            self.$root.$emit('displayalert','Missing Permission: View Comments');
                        } else if (response.status === 204) {
                            self.comments = [];
                        } else if(!response.ok) {
                            response.json()
                                .then(data => self.$root.$emit('displayalert', data.errors))
                                .catch(error => self.$root.$emit('displayalert', error.status + ' ' + error.statusText));
                        } else {
                            response.json()
                                .then(data => self.comments = data.comments)
                                .catch(error => self.$root.$emit('displayalert', error));
                        }
                    }
                )
                .catch(error => self.$root.$emit('displayalert', error));
        }
    }
};

Apologies for the lengthy code snippet above, I tried to include relevant details. Could someone please guide me on how to automatically load the data on this component when it first loads?

Thank you in advance for your help.

Answer №1

The mounted method is async, which adds a level of complexity to the process.



Here's an example similar to what you're attempting to accomplish:

new Vue({
  el: "#app",
  data: {
    placeId: 1,
    sight: "",
    sightImages: [],
    slideIndex: 1
  },
  mounted() {
    var self = this;
  fetch(`https://jsonplaceholder.typicode.com/albums/${this.placeId}/photos?_start=1&_end=10`)
      .then(response => {
        if (response.ok) {
          return response;
        } else {
          if (response.status === 401) {
            alert("401");
            //self.$root.$emit("notloggedin");
          }
          if (response.status === 403) {
            alert("403");
            //self.$root.$emit("displayalert", "Missing Permission: View Comments");
          }
          if (response.status === 204) {
            alert("204");
            //self.comments = [];
          }
        }
      })
      .then(response => response.json())
      .catch(error => {
        console.log("ERROR: " + error);
      })
      .then(data => {
        self.sight = {
          id: data[0].albumId
        };
        self.sightImages = data;
      })
      /** IF YOU REMOVE THIS, THINGS WON'T WORK CORRECTLY */
      .then(() => {
        self.showSlides(self.slideIndex);
      });
    /** */
  },
  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", "");
      }
      console.log(slides[0]);
      console.log(document.getElementsByClassName("mySlides").length);
      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));
    }
  },
});
.demo-cursor {
  width: 3% !important;
  cursor: pointer;
  margin: 0px 2px
}

.sight-photos {
  width: 6%;
}

.row {
  display: inline-block;
}

.cntrlbtn {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

<div id="app">
  <div class="wrapper">
    <div class="sight-container">
      <p class='sight-name'>Sight Id: {{ sight.id }}</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="image.thumbnailUrl">
        </div>
        <a class="cntrlbtn" @click='plusSlides(-1)'>❮</a>
        <a class="cntrlbtn" @click='plusSlides(1)'>❯</a>
        <div class="caption-container">
          <p id="caption"></p>
        </div>
        <div class="row">
          <img v-for='(image, index) in sightImages' class="demo-cursor" :src="image.url" @click="currentSlide(index + 1)">
        </div>
      </div>
    </div>
  </div>
</div>



You may want to consider a solution like the following:

const self = this;
fetch(url, options)
  .then(response => {
    if (response.ok) {
      return response;
    } else {
      if (response.status === 401) {
        self.$root.$emit("notloggedin");
      }
      if (response.status === 403) {
        self.$root.$emit("displayalert", "Missing Permission: View Comments");
      }
      if (response.status === 204) {
        self.comments = [];
      }
    }
  })
  .then(response => response.json())
  .catch(error => {
    self.$root.$emit("displayalert", error);
  })
  .then(data => {
    self.comments = data.comments;
  });

Answer №2

Ah-ha! I finally solved it!

The culprit in the code was this particular line:

self = this;

Initially, it was referencing the wrong context when the code was executed for the first time, causing an issue. Once I replaced it with

let self = this;

All the problems magically disappeared.

Sometimes computers can be so frustrating, they always do exactly what I tell them to do, not what I actually mean!

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

The onUpdate function does not seem to be functioning as expected in the react-custom-scrollbars

In my React.js application, I am utilizing the "react-custom-scrollbars" component. My goal is to invoke a method each time a user scrolls. To achieve this, I have attempted using the onUpdate method. <div className="thumbs-panel"> <Scrollbar ...

What is the method for showcasing background images sequentially?

css code #intro { position: relative; background-attachment: fixed; background-repeat: no-repeat; background-position: center top; -webkit-background-size: cover; -moz-background-size: cover; backgr ...

Learn how to successfully upload an image using React and Node without having to rely on

I am currently exploring file uploading in react/node. Instead of passing files directly into the API request, I am passing them within the body of the request. Here is a snippet of my react code: import React, { Component } from 'react'; import ...

The offset value was inconsistent in the desktop version of Firefox

Could you take a look at my code on the fiddle link, Here is the code snippet: <body> <div id="content" style="width:400px; height:110px;"> <svg id="circle" height="300" width="300"> <circle cx="150" cy="150" r="40" st ...

Executing the beforeRouteLeave navigation guard on a vue component for testing purposes

I am facing a challenge with unit testing the routing behavior of a vue component using jest. Specifically, when navigating away from the component, the 'beforeRouteLeave' guard in Vue-router is not triggering during testing, even though it works ...

Using Laravel with Vue and <router-link> does not update the content as expected

For my project, I am using Laravel with Vue. On the main page, I have listed all articles and when a user clicks on a specific article, a new page opens displaying that article with other prominent articles shown on the side like this: .https://i.stack.img ...

What is the process of invoking Link manually in React-router?

I am working on a component that is passed a <Link/> object from react-router as a prop. When the user clicks on a 'next' button within this component, I need to manually trigger the <Link/> object. Currently, I am using refs to acce ...

Enhancing the current Node.js, Express, MongoDB, and Socket.io stack with the integration of AngularJS

After spending some time developing a web app using Node.js, Express, MongoDB, Mongoose and Socket.io, I've successfully released version one. Looking ahead to version two, my plan is to revamp the UI completely and switch to a front-end framework lik ...

Regular expressions for URLs in routers

I am currently in the process of constructing a navbar that will receive links from a prop. These links could either be router links or hyperlinks, which is why I want to utilize regex to check if the first character is /. If it is, then I will use push; o ...

Utilizing an EJS template within an express.js application to extract and assign data to a variable

Is there a way to transfer data from my node.js (express) app directly to a variable within the <script> tag on the page? On the server-side, I have the following code: let tmp = JSON.stringify(await f(i)); console.log(tmp); //correct data [{"i ...

Angular2-starter configuration setup with environment-based variables (such as .env or .conf) for testing and production settings

Frameworks like PHP Laravel often include files for local configuration, separate from dev, test, and production environments. How can a configuration file be provided for an angular-starter project that contains all local environment variable values (su ...

What is the process for attaching two components to one router in a view?

Currently, I am delving into the world of vue programming. My latest endeavor involves integrating the Gantt chart code from dhtmlx into my vue project. The example provided showcases the division of Gantt chart creation code across two files, with one c ...

Implementing server-side range filter in vue-tables-2: A step-by-step guide

I am currently using a server-side VueTables-2 component to display data from the database. The table includes columns with numeric, textual, and date values. My issue lies with filtering the numeric columns. I am trying to incorporate options for range f ...

Employing a pair of interdependent v-select components to prevent any duplicate entries

I am currently working with two v-select boxes that share similar data. In my scenario, I extract attachments from an email and load them into an array. The issue I encountered is that the first select box should only allow the selection of one document, w ...

When using the setTimeout function, jQuery's .submit() method may fail to pass data to PHP

I'm attempting to enhance the login form with an effect that triggers a 1-second delay before proceeding to PHP. I tried implementing a setTimeout() function within the .submit event handler along with e.preventDefault() to create the delay, but enco ...

Can you explain the concept of middleware and the app.use method in Express?

Before we dive in, I just want to clear the air that this might seem like a repeat question. However, I am curious to hear your explanation of what middleware is. I've noticed similar inquiries on Stack Overflow, but I'm hoping you can provide so ...

When an element is appended, its image height may sometimes be mistakenly reported as

I am dynamically adding divs and I need to retrieve the height and width of an image. Based on this information, I have to apply CSS to the MB-Container class. For example: if the image is portrait orientation, set container width to 100%. If it's ...

Issue with displaying Font-awesome icons within a Vue.js v-for loop - icons are showing up as text instead of rendering properly

When looping an element four times with a v-for in Vue, all content renders correctly except for Font Awesome icons which show up as HTML text. Below is the code snippet causing the issue: HTML: <div class="second-section-paragraph-1" v-for=& ...

Error encountered: Unable to compute centroids with Three.js / Collada due to an undefined value

There seems to be an issue when utilizing the ColladaLoader JavaScript, as it throws an error stating "undefined is not a function" in line 2403 of ColladaLoader.js. Despite following the example provided by simply loading the .dae file: var loader = new ...

Issue with Highcharts failing to render points on regular intervals

I am facing an issue where the line graph in my frontend application using highcharts disappears or fails to draw to the next new data point every 30 seconds. Can anyone provide insight into why this might be happening? Check out the fiddle: http://jsfidd ...