Using VueJS to ensure that an element is ready before executing a local JavaScript file

I am currently working on a project that involves running multiple components, JavaScript files, and elements in a specific order.

First, I include opensheetmusicdisplay.min.js in my index.html file without any issues.

Secondly, I have <div id="xml">

Third, there is xml-loader.js which relies on both the "xml" div and opensheetmusicdisplay.min.js

Here is the content of my index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script rel="preload" src="<%= BASE_URL %>js/osmd/opensheetmusicdisplay.min.js"></script>    
  </head>

  <body>
    <div id="xml2">words go here</div>
    <div id="app"></div>   
  </body>
</html>

Below is the JavaScript code I am trying to test:

window.onload = function() {
    alert("xx == ", document.getElementById("xml2"));
}

alert("xx2 == ", document.getElementById("xml2"));

alert(JSON.stringify(opensheetmusicdisplay, null, 1));

When I run this, both instances of "xml2" show blanks. However, the opensheetmusicdisplay does display data, indicating it is reading from the source in the head section of index.html.

An error regarding the console was pointed out - TypeError: document.getElementById(...) is null. Additionally, I made an oversight in using the alert function with two arguments which I will address later.

Now let's focus on main.js where various comments outline different ideas:

// vue imports and config import Vue from 'vue' import App from '@/App' import VueRouter from 'vue-router'

Vue.use(VueRouter) Vue.config.productionTip = false

// page imports
import Notation from '@/components/Notation'
import HomePage from '@/components/HomePage'

import { FoundationCSS } from  '@/../node_modules/foundation-sites/dist/css/foundation.min.css'
Vue.component('foundation-css', FoundationCSS)

import SideNav from '@/components/SideNav'
Vue.component('side-nav', SideNav);

import * as XmlJs from '@/../public/js/osmd/xml-loader.js'
Vue.component('xml-js', XmlJs)

const router = new VueRouter({
    mode: 'history',
    routes: [
        { path: '/',
          components: {
              maininfo: HomePage
          }
        },
        { path: '/chromatic-scales/c-chromatic-scale',
          components: {
              maininfo: Notation
          }
        }
    ]
})


new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
})

I have globally registered XmlJs because it seems to be the only solution that works consistently. It is then embedded in Notation.vue as follows:

<template>
<div>

  <div id="xml">
    {{ notation.data }}
  </div>
  <xml-js />
</div>
</template>

<script>
import axios from 'axios'

export default ({
data () {
return {
notation: null,
}
},
mounted () {
axios
    .get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
    .then(result => (this.notation = result))
}})
</script>

<style scoped></style>

The primary objective lies with xml-loader.js, which retrieves data from <div id="xml"> and processes it to render the desired output. The challenge arises when attempting to wait for the information within {{ notation.data }}

As I navigate through the complexities of vuejs and frontend JavaScript frameworks, I acknowledge that there is room for optimization in the current code structure.

Answer №1

A common issue known as a race condition arises when a DOM element is not yet available at the time it's being accessed. The best approach to avoid this problem is to refrain from accessing Vue-created DOM elements outside of the Vue component itself. It's essential to remember that DOM elements are only ready for manipulation after an asynchronous request has been completed:

<template>
<div>
  <div ref="xml" id="xml">
    {{ notation.data }}
  </div>
  <xml-js />
</div>
</template>

<script>
import axios from 'axios'

export default ({
data () {
return {
notation: null,
}
},
async mounted () {
  const result = await axios
    .get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
  this.notation = result;
  this.$nextTick(); // waiting for re-rendering
  renderXml(this.$ref.xml); // passing DOM element to external renderer
}})

Answer №2

To incorporate xml-loader.js into Notation.vue as a function, follow these steps:

mounted () {
  axios.get(PATH).then(result => {
    this.notation = result
    let xmlData = parseXML(result)
    processData(xmlData)
  }
},
methods: {
  processData (data) {
    // perform actions on data
  }
}

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

How to create a vertical dashed line using React Native

https://i.sstatic.net/Mhbsq.png Looking for advice on implementing dotted vertical lines between icons in React Native. Any suggestions? ...

Alternating row colors using CSS zebra striping after parsing XML with jQuery

After successfully parsing XML data into a table, I encountered an issue with applying zebra stripe styling to the additional rows created through jQuery. Despite my efforts to troubleshoot the problem in my code, I remain perplexed. Below is a snippet of ...

JavaScript salary calculation function not functioning properly

Once the user inputs the employee's name and the number of hours they worked on the HTML form, the submit button captures this information and stores it in variables for calculating their pay. The script also factors in overtime pay. Despite feeling l ...

Unlock the Power of Angular: Leveraging ViewEncapsulation.Native to Access HTML Elements

I am encountering an issue where I am receiving an error when trying to access an HTML element by ID. The problem arises when I attempt to access the classList upon a user clicking a button to apply a different style class to the element. The class list an ...

Assigning the image source to match the image source from a different website using the image ID

Would it be possible to retrieve the URL of an image from a different webpage using its img ID, and then implement it as the image source on your own website? This way, if the image is updated on the original site, it will automatically update on yours as ...

How can we determine when a row has been modified while using a list of floating-left LIs?

Check out this list of products for an example: I have a function that is triggered on document ready which goes through each item in the list and adjusts the height of a span wrapping the image to ensure uniform spacing. My question is, is it possible f ...

Tips for increasing visibility for your Google Analytics Embed API Custom Components

I recently tried to incorporate some code I found at the following link: After downloading the files view-selector2 and date-range-selector, I saved them in my local directory. I made a modification to the code: var accountSummaries = require(['&ap ...

Remember a MySQL query using JavaScript

For quite some time, I've been on a quest to unveil the solution to this issue that seems relatively straightforward, yet continues to elude me. The crux of the matter is my desire to "recall" a functional mysql query. With an HTML button and a span ...

Error in React JS: TypeError - Attempting to extend a class with an undefined value, which is not a

I am new to React and experimenting with a code example on https://jscomplete.com/repl. Currently, my code appears as follows: let data = [ { name:"Paul O’Shannessy", avatar_url:"https://avatars1.githubusercontent.com/u/8445?v=4", c ...

What is the best way to pass a prop into the <router-link>?

If I replace this {{ name }}, the result is "campaigns" Now, I want to use that in my link <router-link :to="'/' + '123' + '/' + item.id"> {{ item.name }}</router-link> I attempted to substitute '1 ...

Error: NextJS Client-Side Rendering Issue

I find this situation quite perplexing... Everything seems to be working fine except for the onClick code and useEffect code. I attempted running document.querySelector('button'); in the console, but it returned undefined. It appears that JavaSc ...

What is the process for uploading a file and storing it in a specific directory?

Creating HTML Form for File Upload: <div style="width:200px"> <form action="javascript:_bulkUser();" method="post" enctype="multipart/form-data"> Select File:<input type="file" name="fname"/><br/> <input type="submit ...

Pressing the button will allow you to select and copy the text within the

I am looking to incorporate a mock-chat feature into my website. The concept is to type something on the website, then click a button next to it which will move the text to a frame above. I attempted this using a textarea and even found a code for selectin ...

Is it necessary to include a request in the API route handler in Next.js when passing parameters?

In my API route handler, I have a function for handling GET requests: import { NextRequest, NextResponse } from "next/server"; export async function GET(req: NextRequest, { params }: { params: { id: string } }) { const { id } = params; try { ...

What is the best way to implement my Vanilla JS Array manipulation technique in a ReactJS environment?

https://i.sstatic.net/ZRGsS.jpgMy REST API development is in its final stages, and I'm currently facing a challenge with converting an array received from the backend into either a Nested Object of Objects or an array of objects. This conversion would ...

Swap out the HTML button element for text once the form is submitted

On the main page, I have a button that opens a modal when clicked. Inside the modal, there is a form with a submit button that closes the modal and returns to the main page. After closing the modal, I want to change the HTML button on the main page to plai ...

End of Items Trigger for Custom jCarousel

Currently, I am using jCarousel to display a list of items. Imagine there are 8 items in total. Initially, I show 4 items, wait for 10 seconds, then scroll to reveal the remaining 4 items. My goal is to then display the first four items again and trigger a ...

Issue encountered: Next.js has failed to hydrate properly due to a discrepancy between the initial UI and server-rendered content

Uncertain about the cause of this error? The error seems to disappear when I remove the provided code segment. What is triggering this error in the code snippet and how can it be fixed? <div className="relative flex flex-col items-center pt-[85.2 ...

tips for accessing variables in jade/pug custom filters

Looking to create a filter in jade/pug? Here's an example of the filter code: pug.filters.testfilter = function (text) { console.log(text); }; Using it in a .pug file: li :testfilter #{tag.date} The tag data is {'date': ISODat ...

transferring function from server to the client module named Next 13

After referencing the documentation for the app directory in Next.js, it is recommended to fetch data inside Server Components whenever feasible. Server Components always carry out data fetching on the server. This advice is particularly helpful for me as ...