Lars Fransén
Lars Fransén

Reputation: 31

Laravel9 Inertia::render Array is converted to Vue3 props Object

I have created the following controller function in Laravel 9

    public function select(Request $request): Response
    {
        // Get all diagnostic events (for selection dropdown)
        $diagnosticEvents = DiagnosticEventResource::collection(DiagnosticEvent::all());

        // Get all answers for selected diagnostic event
        $answers = Answer::select('diagnostic_event_id', 'question_id', 'responder_uuid', 'score')
            ->where('diagnostic_event_id', $request->event_id)
            ->get();

        // Create responder_uuid list and answers array for selected diagnostic event
        $responder_uuids = [];
        $answerArray = [];
        $questions = QuestionResource::collection(Question::all());
        foreach($answers as $answer) {
            if (!in_array($answer->responder_uuid, $responder_uuids)) {
                $responder_uuids[] = $answer->responder_uuid;
            }
            if (!array_key_exists($answer->question_id, $answerArray)) {
                $answerArray[$answer->question_id] = (object)array_merge(
                    ['question' => $questions[$answer->question_id - 1]->description],
                    ['responders' => []]
                );
            }
            if ($answerArray[$answer->question_id]) {
                $answerArray[$answer->question_id]->responders[] = (object)array_merge(
                    ['uuid' => $answer->responder_uuid],
                    ['score' => $answer->score]
                );
            }
        }

        // Get responder data for selected diagnostic event
        $responders = ResponderResource::collection(Responder::whereIn('uuid', $responder_uuids)->get());

        return Inertia::render('Answers/Select', [
            'diagnosticEvents' => $diagnosticEvents,
            'diagnostic_event_id' => $request->event_id == null ? null : (int)$request->event_id,
            'answers' => $answerArray,
            'responders' => $responders,
            'isSchoolAdmin' => Auth::user()->isSchoolAdmin()
        ]);
    }

and a vue3 module starting with the following code

<script setup>
import AuthenticatedLayout from "@/Layouts/Authenticated";
import BreezeLabel from "@/Components/Label";
import {Inertia} from "@inertiajs/inertia";
import {Head} from '@inertiajs/inertia-vue3';
import {ref, watch} from 'vue';
import Index from "@/Pages/Answers/Index.vue";

const props = defineProps ({
    diagnosticEvents: Array,        // All diagnostic events (for selection)
    diagnostic_event_id: Number,    // Id for current diagnostic event
    answers: Array,                 // All answers for selected diagnostic event
    questions: Array,
    responders: Array,
    isSchoolAdmin: Boolean
})

When I run the code I will get a warning saying Invalid prop: type check failed for prop "answers". Expected Array, got Object

When I look at $answerArray in the debugger it is an Array but when I look at props in Chrome DevTools it shows answers: {1: {,...}, 2: {,...},...}

instead of answers: [1: {,...}, 2: {,...},...]

prop responders is also an array included in the Inertia:render response but is transferred correctly responders: [{uuid: ...},...]

Why and what can I do to fix this?

Upvotes: 2

Views: 2075

Answers (1)

Matheus Dal&#39;Pizzol
Matheus Dal&#39;Pizzol

Reputation: 6105

The problem is that $answerArray is an associative array. Internally, Inertia will call PHP's json_encode, which will turn this into an object. You have two options:

1. Change the answers prop type to Object. Use this if the keys are important to you in the Vue side.

2. Create a non associative array from the $answerArray in order to get json_encode to keep it as an array.

return Inertia::render('Answers/Select', [
   // ...
   'answers' => array_values($answerArray),
   // ...
]);

Upvotes: 5

Related Questions