Search code examples
javascriptjsonfunctiondomxmlhttprequest

Getting JSON to display on a page using JavaScript


I don't know why the code in the snippet below returns this error within the 'generateSkillData' function:

Uncaught TypeError: Cannot read property 'forEach' of undefined
    at generateSkillData (script.js:54)
    at loadingDone (script.js:45)
    at XMLHttpRequest.request.onload (script.js:24)

Rather than displaying the results of skills.json (see below an example of one object):

[
{
    "skill": "Python",
    "description": "An increasingly popular server-side language"
}
] 

I have other code that is very similar and runs fine. I borrowed a lot of the functionality from that code.

function getSkillData(errorFunc, successFunc) {
  let request = new XMLHttpRequest();
  request.open("GET", "js/skills.json", true);
  request.onload = function() {
    if (request.status >= 200 && request.status < 400) {
      console.log("Success! The call worked!");
      const data = request.responseText;

      successFunc(data); {
        console.log("Error: no data available");
      }
    };
    request.onerror = function errorFunc() {
      errorFunc();
    };
  };

  request.send();
}

function loadingDone(data) {
  console.log("LOADING DONE");
  skill_box.innerHTML = "";
  const finished_markup = generateSkillData(data);
  const skill_container = document.getElementById("skill_box");
  skill_container.insertAdjacentHTML("beforeend", finished_markup);
};


function generateSkillData(response) {
  let skill_markup = "";
  response.data.forEach(function(thing) {
    skill_markup += formatSkillData(thing);
  });
  return skill_markup;
}

function formatSkillData(item) {
  const markup = `
        <ul>
            <li>${item.skill}</li>
            <li>${item.description}</li>
        </ul>`;
  return markup;
}

function loadingError() {
  console.log("Error loading skills: try again later");
  document.body.insertAdjacentHTML("beforeend", "<strong>An error occured, please try again later</strong>");
};


(function init() {
  getSkillData(loadingError, loadingDone);
})()
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>

  <form id="user_form">
    <label class="user_input_label" for="link">Skill name:</label>
    <input type="text" name="skill" value="" placeholder="Enter a skill..." id="skill">
    <label class="user_input_label" for="price">Skill description:</label>
    <input type="text" name="description" value="" placeholder="Description..." id="description">
    <input class="submit_button" type="submit" value="Submit">
  </form>

  <section id="skill_box">

  </section>

</body>

<script src="js/script.js"></script>

</html>


Solution

  • You have to parse your response to JSON.

    JSON.parse(response);
    

    Insert it just before the for each call. That way you could iterate over it and get the specific objects.