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
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>