0

Here's my issue. I would like to return a value from a fetch function and display it in VUE. I tried to return the entire fetch function but it is returning the function, instead of the value. The other solution was to create a variable, assign it inside the fetch function, and then return the value, but it didn't work either.

Here's my code:

var vm = new Vue({
    el: '#myblogid',
    data: {
      blogs: [],
      cats: [],
      mycat: 'init',
      blogcats: [],
      page: 0,
      greeting: "Load more Posts",
      totalPages: "",
      isLoading: "",
      pageAmp: "&page=",
      apiURL: '/wp-json/wp/v2/posts?per_page=3&page=',
      catUrl: '/wp-json/wp/v2/categories',
      blogcatUrl: '/wp-json/wp/v2/posts?category_slug=',
    },
    created: function () {
      this.fetchblogs();
      this.setCategory();
    },
    methods: {
      fetchblogs: function () {
        let self = this;
        self.page = 1;
        let url = self.apiURL+self.page;
        fetch(url)
        .then(response => response.json())
        .then(data => vm.blogs = data);
      },
      getCategoryName: function(b) {
        let catnames = '';
        let self = this;
        let catId = b.categories[0];
        let url = self.catUrl+'/'+catId;
        fetch(url)
        .then(response => response.json())
        .then((data) => {
          catnames = data.name;
        });
        console.log(catnames)
        return catnames;
      },
      shorterDescription: function(b) {
        let maxLength = 140;
        let trimmedString = b.excerpt.rendered.substr(0, maxLength);
        if (b.excerpt.rendered.length < maxLength) {
          return b.excerpt.rendered;
        } else {
          trimmedString = trimmedString.substr(0,  trimmedString.lastIndexOf(" ")) + " ...";
          return trimmedString;
        }
      },
      loadMore: function() {
        var xhr = new XMLHttpRequest();
        var self = this;
        self.page++;
        self.isLoading = "is-loading";
        var test = self.mycat;
        if (self.mycat == 'init') {
          xhr.open("GET", self.apiURL + self.page);
          xhr.onload = function() {
            self.totalPages = xhr.getResponseHeader("X-WP-TotalPages");
            if (self.page == self.totalPages) {
              self.isShow = false;
            }
            var newPosts = JSON.parse(xhr.responseText);
            newPosts.forEach(function(element) {
              self.blogs.push(element);
            });
            self.isLoading = null;
          };

          xhr.send();
        } else {
          fetch(self.blogcatUrl+self.mycat+self.pageAmp+self.page)
          .then(response => response.json())
          .then(data => data.forEach(function(element) {
            self.blogs.push(element);
          })
          );
        }
      },
      setCategory: function() {
        let self = this;
        let url = self.catUrl;
        fetch(url)
        .then(response => response.json())
        .then(data => vm.cats = data);
      },
      getCategory(event) {
        let self = this;
        let url = self.blogcatUrl+event.target.value;
        let urlinit = self.apiURL+self.page;
        if (event.target.value == 'init') {
          self.isShow = true;
          fetch(urlinit)
          .then(response => response.json())
          .then(data => vm.blogs = data);
        } else {
          fetch(url)
          .then(response => response.json())
          .then(data => vm.blogs = data);
        }
      }
    }
  });
<div class="lazyblock-blogs row testblog" id="myblogid">
  <div class="col-md-12">
    <div class="category">
      <ul>
        <li value="all" class="active">All resources</li>
        <li v-for="cat in cats" :value="cat.slug">{{cat.name}}</li>
      </ul>
    </div>
  </div>
  <div class="col-md-4" v-for="(b, index) in blogs">
    <div class="h-100 box" v-cloak>
      {{getCategoryName(b)}} test
      <img v-bind:src=b.featured_image_url>
      <div v-html=shorterDescription(b)></div>
      <p class="read-more"><a v-bind:href="b.link">Read More <img width="10" src="myimg.svg" alt="arrow right"></a></p>
    </div>
  </div>
  <div class="col-md-12 align-center">
    <button v-if="isShow" id="load-more" class="btn btn-primary margin-center" @click="loadMore(page)">Load more</button>
  </div>
</div>

Everything else is working, except the getCategoryName name. I'm passing the array that I previously created from another endpoint, printing the id, creating another URL, and fetching the URL value. If I console.log the element it will work of course, but there's no way to return the function without obtaining the curly bracket (which I assume, is the entire function).

Any help?

Porcellino80
  • 447
  • 7
  • 32
  • "there's no way to return the function without obtaining the curly bracket (which I assume, is the entire function)" - returning functions? It looks like you may have problems with basic JS syntax. Functions aren't returned here. `{{getCategoryName(b)}}` - you can't get the result from async function in the template. You have problems with promise pattern here. All promises are supposed to be returned from respective functions. All things that should happen as the result of async functions should happen inside .then callback. That's what the dupe question explains. – Estus Flask Jan 25 '22 at 12:19
  • I tried to return the value from the function, but it will return an empty element. I used an improper word of course, but because I found a topic that was suggestion to return the entire fetch function. The result of the issue will be two curly brackets, I thought that particular result was the entire function like it happens in plain js. – Porcellino80 Jan 25 '22 at 13:08
  • Most problems you have here are not specific to Vue, it would be the same in plain JS. Do you talk about these brackets? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#object_literals . Whatever getCategoryName does, it shouldn't be called in the template, more like in `created`, similarly to how you did with other async functions. If you need to do this for an array then this needs to be done in a loop. If you need to do this after `blogs` is set then you need to chain promises until this happen. This code is much easier to write correctly with `async..await` – Estus Flask Jan 25 '22 at 13:27

0 Answers0