0

I am a javascript beginner, I have a multiple choice exam project where I want to get response data for each selected answer. I can do it by typing the code manually but I want to make the code efficient because the data can be more than 50 questions.

heres my best code .

var i;
    for (i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) {
        window['radio' + i] = document.querySelectorAll("input[name='optionTrue" + i + "']");
        window['rubahtombol' + i] = document.getElementById("buton" + i);
    }

    let findSe = () => {
        let selected = document.querySelector("input[name='optionTrue1']:checked").value;
        var soalId = document.getElementById("idSoal1").value;
        var opsiPilih = document.getElementById("jawaban" + selected).textContent
        document.getElementById("pilihan1").textContent = ". " + opsiPilih;
        rubahtombol1.classList.remove("btn-secondary");
        rubahtombol1.classList.add("btn-primary")
    }
    let findSe1 = () => {
        let selected = document.querySelector("input[name='optionTrue2']:checked").value;
        var soalId = document.getElementById("idSoal2").value;
        var opsiPilih = document.getElementById("jawaban" + selected).textContent
        document.getElementById("pilihan2").textContent = ". " + opsiPilih;
        rubahtombol2.classList.remove("btn-secondary");
        rubahtombol2.classList.add("btn-primary")
    }

    radio1.forEach(radioBtn => {
        radioBtn.addEventListener("change", findSe1);
    });
    radio2.forEach(radioBtn1 => {
        radioBtn1.addEventListener("change", findSe2);
    });
    findSe1();
    findSe2();

i'm trying to do this but not working

var i;
    for (i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) {
        window['radio' + i] = document.querySelectorAll("input[name='optionTrue" + i + "']");
        window['rubahtombol' + i] = document.getElementById("buton" + i);
        window['findSe' + i] = () => {
            let selected = document.querySelector("input[name='optionTrue1']:checked").value;
            var soalId = document.getElementById("idSoal1").value;
            console.log(selected);
            var opsiPilih = document.getElementById("jawaban" + selected).textContent
            console.log("aku pilih:" + opsiPilih);
            console.log("id saol:" + soalId);
            document.getElementById("pilihan1").textContent = ". " + opsiPilih;
            window['rubahtombol'+i.classList.remove("btn-secondary")];
            window['rubahtombol'+i.classList.add("btn-primary")];
        }
    }
    radio1.forEach(radioBtn => {
        radioBtn.addEventListener("change", findSe1);
    });
    radio2.forEach(radioBtn1 => {
        radioBtn1.addEventListener("change", findSe2);
    });
    findSe1();
    findSe2();

what i imagine is, i want do that in one looping

  • 1
    Don't use dynamic variables. Put your data in objects and arrays and use array indexing. – Barmar Jan 30 '23 at 21:52
  • (Offtopic) It can help to write your question in https://translate.google.com in your language, copy/paste the translation and fix it if needed... – Roko C. Buljan Jan 30 '23 at 21:52
  • Avoid bloating the `window` scope. Use function scope, const, let, encapsulation etc. – Roko C. Buljan Jan 30 '23 at 21:54
  • The drawback to learning English on Instagram is that you get the impression "im" is a word. It isn't. :) `I am >> Iam >> I'm` – isherwood Jan 30 '23 at 21:58
  • I apologize if my question is not clear, this is the first time I use stackoverflow to ask @RokoC.Buljan – Bayu Pratama Jan 30 '23 at 23:07
  • I've tried using arrays but I still can't get in the sections findSe =(){} @Barmar – Bayu Pratama Jan 30 '23 at 23:10
  • I am confident that you can make your script _a lot easier_, if you apply some _DOM navigation relative to each clicked button_ in your event listener function. In order to come up with a suggestion we need to see a representative part of your generated HTML for the questions. – Carsten Massmann Jan 31 '23 at 05:24

2 Answers2

0

Your second approach looks pretty close, but you need to make i local to the loop body. See JavaScript closure inside loops – simple practical example

But you can make it a little cleaner with OOP.

class Button {
    contructor(i) {
        this.index = i;
        this.radio = document.querySelectorAll(`input[name='optionTrue${i}']`);
        this.rumbahtombol = document.getElementById("buton" + i);
        this.radio.addEventListener("change", this.findSe.bind(this));
    }

    findSe() {
        let selected = document.querySelector(`input[name='optionTrue${this.index}']:checked`).value;
        let soalId = document.getElementById(`idSoal${this.index}`).value;
        let opsiPilih = document.getElementById("jawaban" + selected).textContent;
        document.getElementById(`pilihan${this.index}`).textContent = ". " + opsiPilih;
        this.rubahtombol.classList.remove("btn-secondary");
        this.rubahtombol.classList.add("btn-primary")
    }
}

for (let i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) {
    new Button(i);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • thank you @barmar I have successfully completed it. I need to change your code a bit and it works. do i need to share what i changed ? – Bayu Pratama Jan 31 '23 at 14:49
  • If I missed something significant, you should post a better solution as your own answer and accept that. – Barmar Jan 31 '23 at 16:57
  • I just can't explain why because I'm completely new to javascript, if I make a mistake please correct me. thankyou – Bayu Pratama Jan 31 '23 at 17:09
0

i did a little change from the code made by @Barmar and it worked

class Button {
    contructor(i) {
        let radio = [];
        this.index = i;
        radio[i] = document.querySelectorAll(`input[name='optionTrue` + i + `']`);
        radio[i].forEach(radioBtn => {
            radioBtn.addEventListener("change", this.findSe.bind(this));
        });
    }

    findSe() {
        let rubahtombol = []
        let selected = document.querySelector(`input[name='optionTrue${this.index}']:checked`).value;
        let soalId = document.getElementById(`idSoal${this.index}`).value;
        let opsiPilih = document.getElementById("jawaban" + selected).textContent;
        document.getElementById(`pilihan${this.index}`).textContent = ". " + opsiPilih;
        rubahtombol = document.getElementById(`buton${this.index}`);
        rubahtombol.classList.remove("btn-secondary");
        rubahtombol.classList.add("btn-primary")
    }
}

for (let i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) {
    new Button(i).contructor(i);
}