1
votes

I have a few components, javascript, and elements that needs to be ran in a certain order.

1st - opensheetmusicdisplay.min.js which I have in my index.html file. This isn't an issue.

2nd - <div id="xml">

3rd - xml-loader.js which depends on both the "xml" div and opensheetmusicdisplay.min,js

This is the 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>

And this is the JavaScript part I'm attempting 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, they both instances of "xml2" show blanks. The opensheetmusicdisplay does show data, which means it is reading from the source in the head section in index.html

It was pointed out to me in the comments that alert only take one argument. That's a mistake that I'm going to let sit for the moment. The error in the console is TypeError: document.getElementById(...) is null.

Now, this is the main.js. There are a lot of comments because of my various 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'
// component imports and registration
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 Osmd from '@/../public/js/osmd/opensheetmusicdisplay.min.js'
// Vue.component('osmd-js', Osmd)
// import { OsmdJs } from '@/components/Osmd'

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

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


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

I registered XmlJs as global because this is the only way out of 100 things that actually works. I then embed it in Notation.vue like so:

<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 last file is the meat and potatoes of what I'm trying to do. The xml-loader.js slurps the data from <div id="xml"> and does whatever magic the program does in order to render the output I want. The issue is that there doesn't seem to be anyway to wait for the stuff in {{ notation.data }}.

I am new to using vuejs and front-end javascript frameworks in general. I do recognize the code is probably not optimal at this time.

2
alert takes a single argument - so alert("xx == ", document.getElementById("xml2")); will only ever show xx == ... have you considered using debugging tools that exist in your browser ... console.log for exampleJaromanda X
@JaromandaX Yes, you are right. There is nothing coming back from the "xml" div though. That still shows as null. I have a website where this stuff works w/o VueJS, so I know this does work before trying out VueJS on this version. It just seems very difficult to get any local js files running and it's even harder to get things to see each other. Those are the main issues I'm dealing with here.dizzystar
What does coming back from the "xml" div mean? What exactly do you try? Please, provide a way to replicate the problem. As long as you run the script below div, document.getElementById("xml2") will output the element and not null.Estus Flask
@EstusFlask -> TypeError: document.getElementById(...) is null. That's the error in the console.dizzystar
Please, provide a way to replicate the problem. Codesandbox or something. See stackoverflow.com/help/mcveEstus Flask

2 Answers

2
votes

There is race condition where DOM element is not available at the time when it's accessed. The solution is to not access DOM elements created by Vue outside of it. DOM element is ready for use only after asynchronous request:

<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(); // wait for re-render
  renderXml(this.$ref.xml); // pass DOM element to third-party renderer
}})
0
votes

You can import xml-loader.js into the Notation.vue as a function. Then you can simply do something like this:

mounted () {
  axios.get(PATH).then(result => {
    this.notation = result
    let xmlResult = loadXML(result)
    doSomethingWithResult(xmlResult)
  }
},
methods: {
  doSomethingWithResult (result) {
    // do something
  }
}