Using Vue.js and axios to manipulate injected HTML content

I am currently working on a project using vue.js and axios to fetch the latest post content from a specific category of a WordPress site using REST API. The post content is always in the form of an ordered list (OL) which will then be displayed as a carousel. Although I have successfully injected the OL, I am facing issues with manipulating it. Can someone kindly help me identify the problem in my JavaScript code? While I know this task can be easily accomplished using jQuery, I am eager to explore something new.

Here is the HTML:

<div class="frame ajax announcements">
  <h1 id="announcements-title" class="material ajax-title">Announcements<span class="title-this-week"></span></h1>
  <div id="app" class="ajax-body material" v-html="posts[0].content.rendered">
  </div>
</div>

And here is the JS code:

var tcnt = 0;

new Vue({
  el: '#app',
  data: {
    posts: []
  },
  created() {
    axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/categories/')
    .then((response) => {
      var categoryId = 0;
      response.data.forEach(function(category){
        if (category.slug == 'announcements') {
          categoryId = category.id;
          console.log('Category ID: ' + category.id);
        }
      });
      return categoryId;
    })
    .then((categoryId) => {
      console.log(categoryId);
      return axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/posts/', {
        params: {
          categories: categoryId,
          per_page: 1,
          status: 'publish'
        }
      });
    })
    .then((response) => {
      console.log(response.data);
      this.posts = response.data;
    })
    .catch((error) => {
      console.log(error.message);
    })
  },
  mounted() {
    var announcements = document.querySelectorAll('.frame.ajax .ajax-body ol li');
    console.log(announcements.length);
    setInterval(function(){
      var target = announcements.length % tcnt;
      for (i = 0; i < announcements.length; i++) {
        if (i == target) {
          announcements[i].style.display = 'block';
        }
        else {
          announcements[i].style.display = 'initial';
        }
      }
      tcnt++;
    }, 1000);
  }
});

Answer №1

There seems to be a timing issue at play here.

To resolve this, it's crucial to grasp the asynchronous nature of Javascript.

If you are performing `document.querySelectorAll('frame.ajax .ajax-body > ol > li')` in the mounted hook, chances are that the ajax request hasn't returned yet. Consequently, the DOM elements have not been created and the functionality may not work as intended.

One effective solution is to encapsulate the DOM manipulation code within a method and execute it only after the ajax response has been received.

Take a look at the listManipulation method:

// Vue instance
var tcnt = 0;

new Vue({
    el: '#app',
    data: {
        posts: []
    },
    // Lifecycle hook
    created() {
        axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/categories/')
            .then((response) => {
                var categoryId = 0;
                response.data.forEach(function(category) {
                    if (category.slug == 'announcements') {
                        categoryId = category.id;
                        console.log('Category ID: ' + category.id);
                    }
                });
                return categoryId;
            })
            .then((categoryId) => {
                console.log(categoryId);
                return axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/posts/', {
                    params: {
                        categories: categoryId,
                        per_page: 1,
                        status: 'publish'
                    }
                });
            })
            .then((response) => {
                console.log(response.data);
                this.posts = response.data;
                
                // Execute listManipulation after DOM update
                this.$nextTick(() => {
                    this.listManipulation();
                })
            })
            .catch((error) => {
                console.log(error.message);
            })
    },
    methods: {
        listManipulation() {
            var announcements = document.querySelectorAll('frame.ajax .ajax-body > ol > li');
            console.log(announcements.length);
            
            // Periodically toggle display property
            setInterval(function() {
                var target = announcements.length % tcnt;
                
                for (i = 0; i < announcements.length; i++) {
                    if (i == target) {
                        announcements[i].style.display = 'block';
                    } else {
                        announcements[i].style.display = 'initial';
                    }
                }
                
                tcnt++;
            }, 1000);
        }
    }
});

$nextTick ensures waiting for the DOM update before executing subsequent code.


In a Vue project, directly manipulating the DOM is generally discouraged. Vue utilizes Virtual DOM to track changes, so modifying the actual DOM might result in conflicts during future updates.

Considering your task of controlling display, exploring v-if would be more appropriate.

Answer №2

Here is an illustration of how to create a carousel without using jQuery or any DOM operations:

var app = new Vue({
el: '#app',
data() {
return {
list: [1,2,3,4],
curIndex: 0
}
},
created () {
window.setInterval(_=>{
if(this.curIndex+1>this.list.length-1){
this.curIndex = 0;
}else{
this.curIndex++
}
},3000)
}
})
.wrapper{
width: 200px;
height: 100px;
position: relative;
}
.wrapper>div{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100px;
line-height: 100px;
text-align: center;
color: #fff;
}
.wrapper>div:nth-child(1){
background: red;
}
.wrapper>div:nth-child(2){
background: blue;
}
.wrapper>div:nth-child(3){
background: orange;
}
.wrapper>div:nth-child(4){
background: yellow;
}
.fade-enter,.fade-leave-active{
opacity: 0;
}
.fade-enter-active,.fade-leave-active{
transition: opacity .5s ease-in-out;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <transition-group tag="div" class="wrapper" name="fade">
   <div v-for="(item,index) of list" :key="index" v-show="index==curIndex">
{{item}}
</div>
</transition-group>
</div>

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

Is there a way to utilize the jQuery Ajax API to load a PHP page that contains an abundance of images and text?

When using the .load() or .ajax() api of jQuery to request a PHP page from the server, do you need to ensure that the PHP page is complete with all tags and markings, as well as containing database connection details? I attempted to link a PHP page using ...

Tips for keeping a reading item in place while scrolling

To enhance the user experience, I would like to improve readability without affecting the scroll position. Question: Is there a way to fix the scrolling item at a specific position (item with the .active class)? I am looking to maintain a consistent read ...

The module 'safe-buffer' is not found by NPM

Ever since installing yarn, I've been unable to use npm. The upgrade for NodeJS went smoothly. Trying to remove npm is proving impossible. Every command I attempt results in the same error message: module.js:487 throw err; ^ Error: Cannot f ...

Focus on selecting the first child <li> element that contains an <a> tag within it

Struggling a bit with selecting only the first child within a li tag that contains a link. HTML: <ul class="dropdown-menu" role="menu" aria-expanded="true"> <li role="presentation" class="dropdown-header">Label</li> <li><a ...

Guide to integrating a deterministic game loop with tick-based mechanics

My current project involves creating a "simple" 3D game using Three.js and incorporating a network framework for multiplayer functionality in the future. After some research, I found that many "action" games utilize a "tick" based game loop to sync clients ...

What is the correct way to establish a backgroundImage path in React JS?

When adding an img, the image path functions as expected: import Background from "./img/bg.webp"; ... <div> <img className='bg' src={Background} /> </div> However, when using the same path for the backgroundImage property, ...

The functionality of the Ajax code is taking an unusually long time

After running my Ajax code, it took a surprising 3 minutes and 15 seconds to load. What could be causing this delay? <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.j ...

Incorporate Object names and Variable names in Javascript programming

I have an object named res and a variable named lea. I need to concatenate. For example: let lea = "abc"; let res = { abc:'steve' }; console.log(res.lea); So my output should be steve. I tried it like this: console.log(res.`${lea}`); ...

What causes certain event handlers to be activated when using dispatchEvent, while others remain inactive?

When it comes to event-based JS, there are two main APIs to consider: event listeners and event handlers. Event listeners can be registered using addEventListener, while event handlers are typically registered with an API similar to target.onfoobar = (ev) ...

What is the best way to apply a mask to a textbox to format the date as MM/yyyy using a mask

In my asp.net application, I have a TextBox for entering Credit card date (month & year only). I tried using the 'TextBox with masked edit extender' and set Mask="99/9999" with Mask Type="Date. However, it is not working as expected - it only wor ...

Utilizing Google's Recaptcha v2 to enhance website security and effectively prevent

My website incorporates an ajax form with Google reCAPTCHA. I have utilized event.preventDefault() to prevent the page from refreshing. Prior to integrating the captcha, everything functioned correctly. However, now whenever I attempt to submit the form, I ...

Perplexing behavior displayed by non-capturing group in JavaScript regular expressions

Here's a straightforward question for you. Regex can sometimes get tricky, so thank goodness for simplifying things... In the URL, there's a query parameter labeled ?id=0061ecp6cf0q. I want to match it and only retrieve the part after the equal ...

Having trouble setting State in React with Typescript?

I have encountered an issue with merging strings in an array. Despite successfully joining two strings and logging the result using console.log('Dates: ' + mergedActions), the merged string doesn't seem to be set in this.state.MergedAllActio ...

Highlight dates in Vue.js that are overdue using a date filter

Currently, I have a Vue filter set up to display dates in a visually appealing way. However, I am looking to enhance the filter by adding a feature that would highlight dates in red if they are overdue (meaning the date is earlier than the current date). I ...

Error in Node.js: [Error: Query parameter should not be empty]

I've been recently focusing on a project that involves sending the required name to my profile.js file using a POST request. However, whenever I try to access console.log(req.body.bookName) (as the data being sent is named bookName), it shows an error ...

Chart rendering failure: unable to obtain context from the provided item

I am encountering an issue while trying to incorporate a chart from the charts.js library into my Vue.js and Vuetify application. The error message that keeps popping up is: Failed to create chart: can't acquire context from the given item Even af ...

reconfigure components by resetting settings on a different component

In the interface, I have a section that displays text along with a unique component titled FilterCriteriaList. This component includes custom buttons that alter their color when clicked. My goal is to reset the settings in the FilterCriteriaList component ...

Tips on sending asynchronous requests to a PHP page using jQuery AJAX

As a newcomer to web development, I am working on creating a social networking website for a college project. One feature I want to implement is updating the message count in the menu every time there is a new message in the database for the user (similar ...

What is the procedure for collapsing a table row or grid?

Looking at this image, I'm trying to find a way to collapse the breakfast row. Any ideas on how I can collapse either the entire tr or with a div? ...

Combining the keys of two objects in JSON

console.log(a) ; // output in console window= 1 console.log(b);// output in console window= 2 var c = {a : b};// Is there a better way to do this? var d = JSON.stringify(c); d = encodeURIComponent(d); I want the final value of d to be {1:2}. ...