1

I am working on a jeopardy project for a bootcamp I'm in. Almost everything is going smoothly, except I cannot get the category titles to populate for the innerHTML of the table heads found in the fillTable function. When I console.log the global 'categories' variable, it shows my array, but when I specify 'categories[i].title' within the for loop, it says undefined.

I've included my entire JS file, so hopefully someone can help me figure out where I'm going wrong. I'm very new to this so any help is greatly appreciated!

let categories = [];
const pickFromArrayAndSplice = (arr) => {
  let randomIdx = Math.floor(Math.random() * arr.length);
  let randomPick = arr[randomIdx]
  arr.splice(randomIdx, 1)
  return randomPick;
}
async function getCategoryIds() {
  const getIds = await axios.get('http://jservice.io/api/categories?count=50');
  let arrayOfIds = getIds.data.map(id => {
    return id.id
  })
  let newArr = [];
  for (let i = 0; i < 6; i++) {
    let randomId = pickFromArrayAndSplice(arrayOfIds)
    newArr.push(randomId);
  }
  return newArr;
}
async function getCategory(catId) {
  let getInfo = await axios.get(`http://jservice.io/api/category?id=${catId}`);
  let title = getInfo.data.title;
  let clues = getInfo.data.clues;
  cluesArr = [];
  for (let i = 0; i < 5; i++) {
    let randomClue = pickFromArrayAndSplice(clues)
    cluesArr.push({
      question: randomClue.question,
      answer: randomClue.answer,
      showing: null
    })
  }
  let categoryData = {
    title: title,
    clues: cluesArr
  }
  categories.push(categoryData);
  return;
}

function fillTable() {
  let tbl = document.createElement('table');
  let tblBody = document.createElement('tbody');
  let gameBody = document.getElementById('game-body')
  let thead = document.createElement('thead');
  //create cells
  for (let r = 0; r < 5; r++) {
    let row = document.createElement('tr');
    for (let c = 0; c <= 5; c++) {
      let cell = document.createElement('td');
      cell.id = `${r}-${c}`
      cell.innerText = `?`
      cell.addEventListener("click", handleClick)
      row.appendChild(cell);
    }
    tblBody.appendChild(row);
  }
  for (let i = 0; i < 6; i++) {
    let newth = document.createElement('th');
    //newth.innerText=categories[i].title;
    newth.innerText = "Category" + i;
    thead.appendChild(newth);
  }
  tbl.appendChild(thead);
  tbl.appendChild(tblBody);
  gameBody.appendChild(tbl)
}

function handleClick(evt) {
  let rowIdx = evt.target.id.split("-")[0]
  let colIdx = evt.target.id.split("-")[1]
  console.log("clicked");
  let myQtarget = categories[colIdx].clues[rowIdx];
  let myShowingValue = myQtarget.showing;
  if (!myShowingValue) {
    evt.target.innerText = myQtarget.question;
    myQtarget.showing = "question"
  }
  if (myShowingValue == "question") {
    evt.target.innerText = myQtarget.answer;
    myQtarget.showing = "answer"
    evt.target.removeEventListener("click", handleClick)
  }
}
async function setupAndStart() {
  let myIds = await getCategoryIds();
  myIds.forEach(async (id) => {
    await getCategory(id)
  })
  //wait for categories before continuing
  fillTable();
}
document.querySelector("#startbt").addEventListener("click", function() {
  setupAndStart();
  this.style.visibility = "hidden";
})
Phil
  • 157,677
  • 23
  • 242
  • 245
CodeLuvr
  • 11
  • 3
  • _"it says undefined"_... nothing ever says this. What is the actual error message and which line does it refer to? – Phil Jan 29 '21 at 01:15
  • 1
    The `myIds.forEach` isn't awaitable inside `setupAndStart()`, you might do some fake awaiting inside the `forEach` loop, but that's a bad pattern here. If you need to await all, you could just use a `await Promise.all( myIds.map( id => getCategory(id) ) )` or turn it into a real for loop and await inside the loop itself – Icepickle Jan 29 '21 at 01:16
  • @Phil I agree that's a good hint, but maybe the fact that the OP is using async/await in an `Array.forEach` loop could be not such a perfect match for the OP? – Icepickle Jan 29 '21 at 01:21
  • 1
    @Phil https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop might be a better match – Icepickle Jan 29 '21 at 01:23
  • 1
    Thanks @Icepickle, I've added that one to the list of duplicates – Phil Jan 29 '21 at 02:06

0 Answers0