anon20010813
anon20010813

Reputation: 155

access a variable declared on a separate JavaScript file in html

I have 2 files the first one is an HTML file the other one is a javascript file. What I was trying to do was define a variable on the javascript file and access it on the Html side. Is it possible? A rough code is attached below but it doesn't work I get favColor is not defined error. thanks in advance.

JS Side

const favColor = "red"

Html side

<script src="pathtojsfile"></script>

<p id="insertHere"></p>

<script>
document.getElementById("insertHere").innerHTML = favColor
</script>

Upvotes: 4

Views: 2886

Answers (3)

connexo
connexo

Reputation: 56770

It is widely considered bad practice to work with global variables. To avoid it, you can make use of ECMAScript Modules, introduced back in 2015 with ES6/ES2015.

This allows your first Javascript, let's name it colors.module.js to export the variable:

export const favColor = 'red';

Then, in your script that needs to access this variable, you import it:

import { favColor } from '/path/to/js/modules/colors.module.js';

For that to work, you need your importing script to have type=module attribute, and the import must be done on top of your Javascript. The script you import from does not need to be included in the page.

Here's some helpful links to get you started with modules:

I've set up a tiny github repo demonstrating this very basic usage of an ES module.

If modules are not an option, e.g. because you must support IE 11, or your build stack doesn't support modules, here's an alternative pattern that works with a single namespace object you attach to the global object window:

// colors.module.js
window.projectNamespace = window.projectNamespace || {};
projectNamespace.colors = window.projectNamespace.colors || {};
projectNamespace.colors.favColor = 'red';

and in your page you access it from that name space:

document.getElementById("insertHere").innerHTML = window.projectNamespace.colors.favColor;

This way you have a single location to put all your globally accessible variables.

Upvotes: 3

julien.giband
julien.giband

Reputation: 2609

Where your variable is declared is not the problem per se, but rather the loading order of scripts. If you want to make sure external scripts are loaded before you execute yours, you can use the load event of window object. It will wait until all resources on your page are loaded though (images, css, etc.)...

const myvar = "Hey I'm loaded";
<!DOCTYPE html>
<html lang="en">
  <head>
      <title>Document</title>
      <script>
          //console.log(myvar); //<- fails
          window.addEventListener('load', e => {
            document.querySelector('#insertHere').innerHTML = myvar;
          });
      </script>
  </head>
  <body>
    <p id="insertHere"></p>
  </body>
</html>

Or you can put all your code in js files, and they will be invoked in the order they are declared.

Edit Given objections and more questions popping in the comments, I'll add this. The best and cleanest way to achieve this remains to put your code in a .js file of its own and put all your <script> tags inside <head>, with yours last, as it relies on others to run.

Then you can either add the attribute defer to your <script> or have everything wrapped in an event handler for DOMContentLoaded so that it gets run after the DOM is fully loaded.

<!DOCTYPE html>
<html lang="en">
  <head>
      <title>Document</title>
      <script src='other1.js'></script> <!-- let's say this one declares myvar -->
      <script src='other2.js'></script>
      <script src='other3.js'></script>
      <script src='myscript.js'></script>
  </head>
  <body>
    <p id="insertHere"></p>
  </body>
</html>

myscript.js

window.addEventListener('DOMContentLoaded', e => {
    document.querySelector('#insertHere').innerHTML = myvar;
});

Upvotes: 1

chrwahl
chrwahl

Reputation: 13060

As the code is written in your example it should work fine. Just like my example here:

<script>
  const favColor = "red";
</script>

<p id="insertHere"></p>

<script>
  document.getElementById("insertHere").innerHTML = favColor;
</script>

But there can be a number of issues if the code is not like this. But the JavaScript code could just go in the same file. Try to separate the html from the JS like this (the code in the script element could be moved to it's own file):

<html>

<head>
  <script>
    const favColor = "red";

    document.addEventListener('DOMContentLoaded', e => {
      document.getElementById("insertHere").innerHTML = favColor;
    });
  </script>
</head>

<body>
  <p id="insertHere"></p>
</body>

</html>

Here I'm also adding the eventlistener for DOMContentLoaded, so that I'm sure that the document is loded into the DOM.

Upvotes: 2

Related Questions