Search code examples
javascripthtmldomjavascript-objectsdom-selection

What is making my variable have a value of null when it selected from the DOM


I am trying to manipulate my HTML elements. I am trying to use dom selectors to change the values of the elements on my page but I keep getting

Uncaught TypeError: Cannot set property 'innerHTML' of null Checking in the browser console to check what the issue is, I found out the logic I was using in dynamically selecting my elements was what was causing the trouble but when I use the same logic to pick up the element, it works well... Can I please get an explanation of why I am getting this behaviour...

Below is a snippet

let timerObj = {
  minutes: 0,
  seconds: 0,
  timerId: 0
}

const soundAlarm = () => {
  let amount = 3;
  let audio = new Audio('Timer_Sound_Effect.mp3');

  const playSound = () => {
    audio.pause();
    audio.currentTime = 0;
    audio.play();
  }

  for (let i = 0; i < amount; i++) {
    setTimeout(playSound, 1200 * i);
  }
}

const updateValue = ((key, value) => {
  if (value < 0) value = 0;
  console.log('Positive Numbers');

  if (key === 'seconds') {
    if (value < 10) value = '0' + value;
  }

  let keySelect = document.getElementById(key);

  keySelect.innerHTML = value || 0
  timerObj[key] = value;
  console.log(keySelect);
  console.log('mins', timerObj.minutes);
  console.log('secs', timerObj.seconds);
})


(function detectChanges(key) {
  console.log('detectChanges');

  let input = document.getElementById(`${key}-input`);

  input.addEventListener('change', () => {
    updateValue(key, input.value);
  })

  input.addEventListener('keyup', () => {
    updateValue(key, input.value);
  })
  return arguments.callee;
})('minutes')('seconds');
body, input, button {
  font-family: 'Montserrat', sans-serif;
}

body {
  margin: 72px 140px 0;
}

#header {
  font-weight: 800;
  font-size: 74px;
}

#controls {
  display: inline-block;
  width: 46%;
  border-right: 1px solid rgba(0, 0, 0, .5);
  padding-right: 42px;
  padding-bottom: 42px;
}

.input-group {
  margin: 26px 0;
}

label {
  display: inline-block;
  width: 24%;
  font-weight: 200;
  font-size: 30px;
  padding: 12px;
}

input {
  width: 60%;
  font-size: 30px;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, .5);
  padding-left: 6px;
  font-weight: 200;
  outline: none;
}

input:disabled {
  background-color: white;
  opacity: .6;
}

button {
  color: white;
  border: none;
  outline: none;
  padding: 12px 62px;
  background-color: #222;
}

button:disabled {
  opacity: .2;
}

button:hover {
  opacity: .5;
}

h2 {
  display: inline-block;
  vertical-align: top;
  font-weight: 200;
  font-size: 144px;
  margin: 12px 0;
  padding-left: 100px;
}
<!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 href="https://fonts.googleapis.com/css2?family=Montserrat:wght@200;400;800&display=swap" rel="stylesheet">
  <title>Clockworks</title>
</head>
<body>
  <h1 id="header">Clockworks</h1>

  <section id="controls">
    <div class="input-group">
      <label for="minutes-input">Minutes</label>
      <input type="number" id="minutes-input" placeholder="0" max="480" min="0">
    </div>

    <div class="input-group">
      <label for="seconds-input">Seconds</label>
      <input type="number" id="seconds-input" placeholder="0" max="59" min="0" step="5">
    </div>

    <button type="button" id="start-btn">Start</button>
    <button type="button" id="pause-btn" disabled>Pause</button>
    <button type="button" id="stop-btn" disabled>Stop</button>
  </section>

  <h2><span id="minutes">0</span> : <span id="seconds">00</span></h2>

  <script src="main.js"></script>
</body>
</html>


Solution

  • You just need to add semicolon to updateValue function

    const updateValue = ((key, value) => {
        if (value < 0) value = 0;
        console.log('Positive Numbers');
    
        if (key === 'seconds') {
            if (value < 10) value = '0' + value;
        }
    
        let keySelect = document.getElementById(key);
    
        keySelect.innerHTML = value || 0
        timerObj[key] = value;
        console.log(keySelect);
        console.log('mins', timerObj.minutes);
        console.log('secs', timerObj.seconds);
    });