Home > Software design >  how to use forEach() on nested objects in an array
how to use forEach() on nested objects in an array

Time:01-23

I'm working on a browser quiz project. I have made an array of objects that has the question choices nested in a further object. I'm struggling to figure out how to compare the users choice of the 4 options to the correct answer in the answers array. I'm stuck because I don't know how to use for each on nested objects inside an array. I could use some advice or a better way to accomplish the same goal

const list = document.createElement('ol');
const li1 = document.createElement('li');
const li2 = document.createElement('li');
const li3 = document.createElement('li');
const li4 = document.createElement('li');

const choices = document.querySelector('.choices');

choices.appendChild(list);
list.appendChild(li1);
list.appendChild(li2);
list.appendChild(li3);
list.appendChild(li4);

const possibleAnswers = ['1', '2', '3', '4', '5', '6', '7'];

const questionPool = [
    {
        questionOne:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionTwo:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionThree:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionFour:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionFive:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionSix:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    },
    {
        questionSeven:
            {
                answers:
                    {
                        answerOne: li1,
                        answerTwo: li2,
                        answerThree: li3,
                        answerFour: li4
                    }
            }
    }
];

CodePudding user response:

If I understood your question correctly I think this answer might help you;

  1. You have to change the structure of your object to make it universal.
  2. You can go through your object array in which each object refers to the object of the 4 answers.
  3. Loop to access the 4 possible answers.

This is how I would do it:

var list = document.createElement("ol");
        var li1 = document.createElement("li");
        var li2 = document.createElement("li");
        var li3 = document.createElement("li");
        var li4 = document.createElement("li");

        let choices = document.querySelector(".choices")

        choices.appendChild(list)
        list.appendChild(li1)
        list.appendChild(li2)
        list.appendChild(li3)
        list.appendChild(li4)

        let questionPool = [
            {
                answers: {
                    1: li1,
                    2: li2,
                    3: li3,
                    4: li4
                }
            },
            {
                answers: {
                    1: li1,
                    2: li2,
                    3: li3,
                    4: li4
                }
            },
            {
                answers: {
                    1: li1,
                    2: li2,
                    3: li3,
                    4: li4
                }
            }
        ];

        questionPool.forEach(element => {
            for(const item in element.answers){
                //here you have access to the 4 li
                console.log(element.answers[item]);
            }
        });

CodePudding user response:

I tried to refactor your code beacause most of it was repetitions for no reason, more details in the comments :

const questionEl = document.createElement('span')
const list = document.createElement("ol");
const nextBtn = document.createElement('button')

const choicesEl = document.querySelector(".choices")

nextBtn.textContent = 'Next'

choicesEl.appendChild(questionEl)
choicesEl.appendChild(list)
choicesEl.appendChild(nextBtn)

// Store you list elements by span (text of the answer) and radio (input field)
const listElements = Array.from({ length: 4 }).map(i => {
    const li = document.createElement('li')
    const radio = document.createElement('input')
    const span = document.createElement('span')

    radio.type = 'radio'
    radio.name = 'quiz-radio'

    li.appendChild(radio)
    li.appendChild(span)
    list.appendChild(li)

    // for convenience
    span.onclick = () => radio.click()

    return { radio, span }
})

// use arrays instead of objects
const questionsPool = [
    {
        question: 'What is the formula for water ?',
        right: 0,
        answers: [
            'H2O',
            'NH3',
            'CO2',
            'C6H12O6',
        ]
    }, {
        question: 'What color is the sky ?',
        right: 1,
        answers: [
            'blue',
            'skyblue',
            'lightblue',
            'navyblue',
        ]
    }
]

let score = 0
let questionIndex = 0

// update the texts in the spans
const updateQuestion = () => {
    const { question, answers } = questionsPool[questionIndex]

    questionEl.textContent = question

    for (let i = 0; i < 4; i  )
        listElements[i].span.textContent = answers[i]
}

// inital rendering
updateQuestion()

nextBtn.onclick = () => {
    // if the user selected the right answer : increment his score
    if (listElements[questionsPool[questionIndex].right].radio.checked) score  
    
    
    // if there is remaining question
    if (questionIndex   1 < questionsPool.length) {
        // go to the next one and update texts
        questionIndex  
        updateQuestion()
    }
    
    else
        // show the final user score
        console.log({ score })
}
<div ></div>

Hope it helped you !

  • Related