Search code examples
laravellaravel-livewire

im new on livewire, som i got stuck on nextquestion button


im creating some simple quiz using livewire 3, before the quiz using data from database...and its got stuck when click nextquestion button, cause once im reach last question after submit it got error "Undefined array key 5"

here my code:

controller exams

<?php

namespace App\Livewire\Student;

use App\Models\Questions;
use Livewire\Component;

class Exams extends Component
{

    public $questions = [
        [
            'question' => 'Apa ibu kota Indonesia?',
            'answers' => [
                'A. Jakarta',
                'B. Bandung',
                'C. Surabaya',
                'D. Medan',
            ],
            'answer' => 'A',
        ],
        [
            'question' => 'Berapa jumlah provinsi di Indonesia?',
            'answers' => [
                'A. 34',
                'B. 33',
                'C. 32',
                'D. 31',
            ],
            'answer' => 'A',
        ],
        [
            'question' => 'Siapa presiden Indonesia saat ini?',
            'answers' => [
                'A. Joko Widodo',
                'B. Prabowo Subianto',
                'C. Anies Baswedan',
                'D. Ganjar Pranowo',
            ],
            'answer' => 'A',
        ],
        [
            'question' => 'Apa nama mata uang Indonesia?',
            'answers' => [
                'A. Rupiah',
                'B. Dollar Amerika',
                'C. Euro',
                'D. Yen Jepang',
            ],
            'answer' => 'A',
        ],
        [
            'question' => 'Apa ibu kota provinsi Jawa Barat?',
            'answers' => [
                'A. Bandung',
                'B. Jakarta',
                'C. Surabaya',
                'D. Medan',
            ],
            'answer' => 'A',
        ],
    ];

    public $score = 0;

    public $questionIndex = 0;
    public $question;

    public function mount()
    {
        $this->question = $this->questions[$this->questionIndex];
    }

    public function nextQuestion()
    {
        $this->questionIndex++;
        if ($this->questionIndex == count($this->questions)) {
            $this->dispatch('quizCompleted', $this->score);
        } else {
            $this->question = $this->questions[$this->questionIndex];
        }
    }

    public function answer(string $answer)
    {
        if ($answer === $this->questions[$this->questionIndex]['answer']) {
            $this->score++;
        }

        // Next question
        $this->nextQuestion();
    }
}

and here on blade view

<div class="quiz">
    <div class="question">
        <div class="question-text">
            {{ $questions[$questionIndex]['question'] }}
        </div>
        <div class="question-answers">
            <input type="radio" name="answer" value="A" id="answer-a" {{ $questions[$questionIndex]['answer'] == 'A' ? 'checked' : '' }}>
            <label for="answer-a">A. {{ $questions[$questionIndex]['answers'][0] }}</label>

            <input type="radio" name="answer" value="B" id="answer-b" {{ $questions[$questionIndex]['answer'] == 'B' ? 'checked' : '' }}>
            <label for="answer-b">B. {{ $questions[$questionIndex]['answers'][1] }}</label>

            <input type="radio" name="answer" value="C" id="answer-c" {{ $questions[$questionIndex]['answer'] == 'C' ? 'checked' : '' }}>
            <label for="answer-c">C. {{ $questions[$questionIndex]['answers'][2] }}</label>

            <input type="radio" name="answer" value="D" id="answer-d" {{ $questions[$questionIndex]['answer'] == 'D' ? 'checked' : '' }}>
            <label for="answer-d">D. {{ $questions[$questionIndex]['answers'][3] }}</label>
        </div>
    </div>

    <div class="">
        <button class="" wire:click="nextQuestion">Selanjutnya</button>
    </div>
</div>

<div class="result" style="display: none;">
    <h2>Hasil</h2>
    <p>Skor Anda: {{ $score }}</p>
</div>

error image enter image description here can someone help me?

after submit last question then showi text "quiz complete" or redirect to route/view


Solution

  • You have an array that has 5 items, meaning you have an index of 4. Like Pippo has said, when you do a count to check if the quiz is complete, you'll have questionIndex == 5.

    When you finish the quiz you dispatch an event, but you don't do anything with the questionIndex or with the blade content in the frontend. Because of this, it will try to access the 6th question, which obviously doesn't exist.

    Easiest way would just be to set a boolean to hide the questions:

    class Exams extends Component
    {
        public bool $finished = false;
    
        public function nextQuestion()
        {
            $this->questionIndex++;
            if ($this->questionIndex >= count($this->questions)) {
                $this->finished = true;
                $this->dispatch('quizCompleted', $this->score);
            } else {
                $this->question = $this->questions[$this->questionIndex];
            }
        }
    }
    
    <div>
        @if($finished)
            <div>
                <span>Good job!</span>
            </div>
        @else
            <div>
                {{ $questions[$questionIndex]['question'] }}
            </div>
        @endif
    </div>