Search code examples
phplaravellaravel-livewire

How to set rules to validate nested array with livewire?


how to set rules and error message for validate nested array on livewire? i am using livewire 2.12 and laravel 10.

viw on blade :

<div class="card card-primary mb-n3">
        <form wire:submit.prevent='submitQuestion' method="POST" class="needs-validation" novalidate="">
            @csrf
            @foreach ($questions as $key => $question)
                <div class="card-body">
                    <div class="section-title">Question {{ $loop->iteration }} </div>
                    <p class="sz-question">{{ $question->description }}</p>
                    <p class="sz-question2">{{ $question->info }}</p>
                    <div class="alert alert-info sz-question3">{!! $question->notes !!}</div>
                    <div class="row">
                        <div class="form-group col-md-7 col-lg-7">
                            <label class="d-block mb-3">Choose<span class="sz-sp"> *</span></label>
                            @foreach ($question->choices as $choice)
                                <div class="form-check form-check-inline">
                                    <input
                                        class="form-check-input"
                                        type="radio"
                                        id="choice-{{ $choice->id }}"
                                        value="{{ $choice->id }}_{{ $question->id }}"
                                        wire:model='answers.{{ $key }}.choice'
                                    >
                                    <label class="form-check-label" for="choice-{{ $choice->id }}">{{ $choice->description }}</label>
                                </div>
                            @endforeach
                            @error('answers.{{ $key }}.choice')
                                <small class="sz-error" id="error-{{ $question->id }}">
                                    <br/> {{ $message }}
                                </small>
                            @enderror
                        </div>
                    </div>
                </div>
            @endforeach

            <div class="card-body text-right mb-0">
                @error('answers')
                    <small class="sz-error" id="error-{{ $question->id }}">
                        <br/> {{ $message }}
                    </small>
                @enderror
            </div>
            <div class="card-body text-right">
                <button
                    type="submit"
                    id="tk-butonSubmit"
                    class="btn btn-success mx-1"
                    wire:loading.class="disabled"
                >Submit <i class="fas fa-check-circle"></i></button>
            </div>

       </form>
    </div>

php :

public $questions;
public $topicId = 1;
public $answers = [];

public function mount()
{
     /** @var Question $questions */
     $questions = Question::whereTopicId($this->topicId)->get();

     $this->questions = $questions;
}

public function render()
{
     return view('livewire.view');
}

example result :

{"answers":[{"choice":"b"},{"choice":"a"}]}

then rules like this:

protected $rules = [
    'answers' => 'required',
    'answers.*.choice' => 'required',
];

submit function :

public function submitQuestion()
{
     $validData = $this->validate();
     Log::info('' . json_encode($validData));
}

when I press the submit button, the validation still gives results even though I haven't filled in all the questions. So, how should i set the rules?


Solution

  • you can use this validation to check if the array is actually filled or empty :

    $rules = [
        'answers' => 'required|array|min:1',
        'answers.*.choice' => 'required',
    ];