Search code examples
javascripteventsaddeventlistener

Cannot access a variable from an event listener in one JavaScript file, in a different JavaScript file


The user can input data values, and then the mean of their values is calculated when they click dataButtonB. I then want to be able to access the value of the mean in a separate javascript file, however I currently cannot get this to work.

sampleB.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <link rel="shortcut icon" href="./images/t.png" type="image/x-icon">
    <title>Document</title>
</head>
<body class="testbody">
    <div class="bsample">
        <div class="headings">
            <h2 class="bheading">Sample B</h2>
            <h3 class="bsubheading">Sample Size</h3>
        </div>
        <input type="number" placeholder="B" autocomplete="off" class="binput input">
        <div id="addItemsB" class="addItems"></div>
        <button type="submit" class="bsubmit submitButton">Submit</button>
    </div>
    <script src="sampleBScript.js"></script>
</body>
</html>

sampleBScript.js

window.addEventListener("DOMContentLoaded", () => {

    const buttonB = document.querySelector('.bsubmit')
    const subheadingB = document.querySelector('.bsubheading')
    const inputB = document.querySelector('.binput')
    const addItemsB = document.getElementById('addItemsB')
    let b = ''
    let totalB = 0;
    let meanB = 0;
    const resultsURL = 'http://localhost:3000/results.html'
    
    buttonB.addEventListener('click', () => {
        let b = inputB.value;
        if(b=='') {
            subheadingB.textContent = 'Values Required'
        } else if (b < 3 || b > 15) {
            subheadingB.textContent = 'Invalid Sample Size'
        } else {
            subheadingB.textContent = 'Data Set';
            inputB.remove();
            buttonB.remove();
            for(i=0; i<b; i++) {
                // Creates number input boxes for sample b
                let input = document.createElement("input")
                input.type = "number"
                input.name = "bValue" + i
                input.classList.add("bValue", "dataValueInput", "dataValueInputB" + i)
                addItemsB.appendChild(input)
                addItemsB.appendChild(document.createElement("br"))
            }
            // Creates button to submit data values for sample b
            let dataButtonB = document.createElement("button")
            dataButtonB.classList.add("dataButton", "dataButtonB")
            dataButtonB.textContent = "Submit B"
            addItemsB.appendChild(dataButtonB)
    
            // When dataButtonB clicked, meanB is calculated
            dataButtonB.addEventListener('click', () => {
                let sampleSizeB = i;
                for(i=0; i<b; i++) {
                    let value = document.querySelector('.dataValueInputB' + i ).value 
                    totalB += parseInt(value)
                }
                meanB = totalB/sampleSizeB;
                console.log(meanB)
                window.location.assign(resultsURL)
            })
        }
    })
})

results.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <link rel="shortcut icon" href="./images/t.png" type="image/x-icon">
    <title>Results</title>
</head>
<body>
    <h3 id="results"></h3>
    <script src="sampleAScript.js"></script>
    <script src="sampleBScript.js"></script>
    <script src="resultsScript.js"></script>
</body>
</html>

resultsScript.js

console.log(meanB)

I'm struggling to access the mean of the data set in resultsScript.js. I'm getting the following errors:

sampleBScript.js:16 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
    at sampleBScript.js:16:13

and:

resultsScript.js:1 Uncaught ReferenceError: meanB is not defined
    at resultsScript.js:1:13

I thought to resolve these errors by using DOMLoadedContent, but I get the same errors whether or not I use that. I've also tried:

// Variables

const buttonB = document.querySelector('.bsubmit')
const subheadingB = document.querySelector('.bsubheading')
const inputB = document.querySelector('.binput')
const addItemsB = document.getElementById('addItemsB')
let a = ''
let totalB = 0;
let meanB = 0;
const resultsURL = 'http://localhost:3000/results.html'

// Main

if (buttonB) {
    buttonb.addEventListener('click', () => {
        let b = inputB.value;
        if(b=='') {
            subheadingB.textContent = 'Values Required'
        } else if (b < 3 || b > 15) {
            subheadingB.textContent = 'Invalid Sample Size'
        } else {
            subheadingB.textContent = 'Data Set';
            inputB.remove();
            buttonB.remove();
            for(i=0; i<b; i++) {
                // Creates number input boxes for sample b
                let input = document.createElement("input")
                input.type = "number"
                input.name = "bValue" + i
                input.classList.add("bValue", "dataValueInput", "dataValueInputB" + i)
                addItemsB.appendChild(input)
                addItemsB.appendChild(document.createElement("br"))
            }
            // Creates button to submit data values for sample a
            let dataButtonB = document.createElement("button")
            dataButtonB.classList.add("dataButton", "dataButtonB")
            dataButtonB.textContent = "Submit B"
            dataButtonB.type = "submit"
            addItemsB.appendChild(dataButtonB)
    
            // Adds functionality to dataButtonB
            dataButtonB.addEventListener('click', () => {
                let sampleSizeB = i;
                for(i=0; i<b; i++) {
                    let value = document.querySelector('.dataValueInputB' + i ).value 
                    totalB += parseInt(value)
                }
                meanB = totalB/sampleSizeB;
                console.log(meanB)
                window.location.assign(resultsURL)
            })
        }
        
    })
}

But with this method it just skips over the event listener entirely, and you get no error, but you also don't get the mean outputted to the console


Solution

  • You changed meanB to meanA in the second code snippet. That makes harder to understand the case. Be more careful please.

    You are trying a wrong worklow:

    • you navigate to another URL (location.assign)
    • open another URL
    • trying to access a local function variable on the previous page

    Looks not a working workflow at all.

    You should store your meanB between the page navigation:

    sessionStorage.setItem('meanB', meanB);
    

    then read it when you need it on the next page:

    console.log(sessionStorage.getItem('meanB'));