How can i set a valid primitive Key for my v-for cycle?

i need to show in a data table a v-dialog that contains basically a restaurant menu structured as an array of objects of arrays of object. That is how i already structured my menu:

menu_ristorante: [       {         primi: [           { nome_portata: "Fettuccine al ragù", quantita_portata: 0 },           { nome_portata: "Tagliatelle alla boscaiola", quantita_portata: 0 },           { nome_portata: "Spaghetti allo scoglio", quantita_portata: 0 },           { nome_portata: "Zuppa di ceci", quantita_portata: 0 },           { nome_portata: "Fettuccine al ragù", quantita_portata: 0 }         ]       },       {         secondi: [{ nome_portata: "Vitello tonnato", quantita_portata: 0 }]       },       {         contorni: [{ nome_portata: "Insalata mista", quantita_portata: 0 }]       },       {         bibite: [           { nome_portata: "Acqua", quantita_portata: 0 },           { nome_portata: "Vino Rosso", quantita_portata: 0 },           { nome_portata: "Vino Bianco", quantita_portata: 0 },           { nome_portata: "Caffè", quantita_portata: 0 }         ]       }     ], 

Then i have inserted my dialog inside a v-data-table that should be triggered by the click of the property item.nome that is the firs column of my table

<v-data-table                 light                 :headers="headers_tabella_persone"                 :items="tabella_persone"                 :items-per-page="10"                 class="elevation-1"               >                 <template v-slot:item.interno="{ item }">                   <v-checkbox v-model="item.interno"></v-checkbox>                 </template>                 <template v-slot:item.nome="{ item }" @click="dialog_visualizza_menu=true">                   <v-dialog v-model="dialog_visualizza_menu" scrollable max-width="300px">                     {{item}}                     <v-card>                       <v-card-title>Seleziona primo</v-card-title>                       <v-divider></v-divider>                       <v-card-text style="height: 300px;">                         <v-radio-group v-model="dialogm1" column>                           <v-radio v-for="portata in menu_ristorante" :key="portata.primi"></v-radio>                         </v-radio-group>                       </v-card-text>                       <v-divider></v-divider>                       <v-card-title>Seleziona secondo</v-card-title>                       <v-divider></v-divider>                       <v-card-text style="height: 300px;">                         <v-radio-group v-model="dialogm1" column>                           <v-radio v-for="portata in menu_ristorante" :key="portata.secondi"></v-radio>                         </v-radio-group>                       </v-card-text>                       <v-card-title>Seleziona bibite</v-card-title>                       <v-divider></v-divider>                       <v-card-text style="height: 300px;">                         <v-radio-group v-model="dialogm1" column>                           <v-radio v-for="portata in menu_ristorante" :key="portata.bibite"></v-radio>                         </v-radio-group>                       </v-card-text>                       <v-card-actions>                         <v-btn color="blue darken-1" text @click="dialog_visualizza_menu = false">Close</v-btn>                         <v-btn color="blue darken-1" text @click="dialog_visualizza_menu = false">Save</v-btn>                       </v-card-actions>                     </v-card>                   </v-dialog>                 </template>               </v-data-table> 

But i receive this error on the key in return

Avoid using non-primitive value as key, use string/number value instead. 

So my entire column item.nome won’t be visible. How can i set a valid primitive key referenced to the stucture of my menu?

EDIT-1 i solved the problem of the key by removing the initial array level from my object and that is my updated object

menu_ristorante: {   primi: [     { id: 1, nome_portata: "Fettuccine al ragù", quantita_portata: 0 },     {       id: 2,       nome_portata: "Tagliatelle alla boscaiola",       quantita_portata: 0     },     { id: 3, nome_portata: "Spaghetti allo scoglio", quantita_portata: 0 },     { id: 4, nome_portata: "Zuppa di ceci", quantita_portata: 0 },     { id: 5, nome_portata: "Fettuccine al ragù", quantita_portata: 0 }   ],   secondi: [     { id: 1, nome_portata: "Vitello tonnato", quantita_portata: 0 }   ],   contorni: [     { id: 1, nome_portata: "Insalata mista", quantita_portata: 0 }   ],   bibite: [     { id: 1, nome_portata: "Acqua", quantita_portata: 0 },     { id: 2, nome_portata: "Vino Rosso", quantita_portata: 0 },     { id: 3, nome_portata: "Vino Bianco", quantita_portata: 0 },     { id: 4, nome_portata: "Caffè", quantita_portata: 0 }   ] }, 

The template is the same

<template v-slot:item.nome="{ item }">               <div style="cursor:pointer;" @click="popolaMenu()">{{item.nome}}</div>             </template>           </v-data-table>         </v-tab-item>         <v-dialog v-model="dialog_visualizza_menu" scrollable max-width="800px">           <v-card>             <v-card-title>Seleziona primo</v-card-title>             <v-divider></v-divider>             <v-card-text style="height: 800px;">                                  <v-radio-group v-model="dialogm1" column>                 <v-radio v-for="(portata) in menu_ristorante" :key="portata.primi">{{portata.primi}}</v-radio>               </v-radio-group>             </v-card-text>             <v-divider></v-divider>             <v-card-title>Seleziona secondo</v-card-title>             <v-divider></v-divider>             <v-card-text style="height: 800px;">               <v-radio-group v-model="dialogm1" column>                 <v-radio v-for="(portata) in menu_ristorante" :key="portata.secondi">{{portata.secondi}}</v-radio>               </v-radio-group>             </v-card-text>             <v-card-title>Seleziona bibite</v-card-title>             <v-divider></v-divider>             <v-card-text style="height: 800px;">               <v-radio-group v-model="dialogm1" column>                 <v-radio v-for="portata in menu_ristorante" :key="portata.bibite">{{portata.bibite}}</v-radio>               </v-radio-group>             </v-card-text>             <v-card-actions>               <v-btn color="blue darken-1" text @click="dialog_visualizza_menu = false">Close</v-btn>               <v-btn color="blue darken-1" text @click="dialog_visualizza_menu = false">Save</v-btn>             </v-card-actions>           </v-card>         </v-dialog> 

I have only put it outsite of the v-data-table to avoid recursive call that will cause crash of my app, so now if i click on a name the pop up is shown but it is populated in the wrong way

enter image description here

Add Comment
2 Answer(s)

You are using an object as a key, that’s why you get that error.

One fast fix would be to change the loop like this:

v-for="(portata, index) in menu_ristorante" :key="index" 

but, the best would be for you to add a unique ID (string or integer) to each of the iterate objects and use it as key.

Buon appetito 😉

Answered on July 16, 2020.
Add Comment

You have to add a key for the loop items in either number or string. But you are adding a object.

I would suggest you to have an id in the object inside menu_ristorante.

Also, you can use the index as key like below.

 v-for="portata, index in menu_ristorante" :key="index" 

The above is not suggested in every place as it doesn’t allow vue to exactly find which element child is changed.

Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.