'Why I cant parse the {{task}} variable inside the v-for in the task-panel child?

The for loop is working properly. When I add a new task panel shows but the {{task}} variable inside the component is not showing. It must be something with the component template.

<span class="col-span-3 bg-blue-200  p-2">{{task}}</span>

I have left all the code down here maybe is something that I don't see. Any idea? Thanks

<body>

    <div id="app">
        <task-input></task-input>
    </div>

    <script>
       let app =  Vue.createApp({  });

       app.component(
           'task-input',
           {
               template:
                   `<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center  mt-5 mx-auto bg-gray-400 ">
                        <input id="taskInput"  v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
                        <button @click="addTask()"  class="text-white font-extrabold uppercase">Add new task</button>
                    </div>
                    <div class="container container mx-auto rounded-top-lg">
                        <div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
                            <h1 class="font-sans text-2xl text-center text-white bg-gray-500  uppercase font-extrabold px-4 py-4">
                                {{title}}
                            </h1>
                            <ul class="bg-white">
                                 <task-panel v-for="task in tasks"/>
                            </ul>
                         </div>
                    </div>`,
                   data() {
                       return {
                           title:"Here is a nice title",
                           task: '',
                           tasks: [],
                       }
                },
               components:['task-panel'],
               methods:{
                   addTask(){
                       this.tasks.push(this.task);
                       this.task='';
                       console.log(this.tasks);
                   }
               }
           },
       );

       app.component('task-panel',{
           template:
                    `<li class="grid bg-gray-200 mt-1">
                        <div class="grid grid-cols-4">
                            <span class="col-span-3 bg-blue-200  p-2">{{task}}</span>
                            <span class="col-span-1 text-center self-center uppercase font-bold">test</span>
                        </div>
                        <div class="flex justify-end bg-gray-300 p-1">
                            <button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
                            <button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
                            <button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
                        </div>
                    </li>
                     `,
           data() {
               return {  }
           },
           props: ['tasks', 'modelValue'],
           computed:{
               tasks:{
                   get(){
                       return this.tasks;
                   }
               }
           }
       });

       app.mount('#app');
   
    </script>
</body>


Solution 1:[1]

The v-for is only in the scope of the parent component. The v-for's iterator prop does not get automatically passed into the task-panel.

You need to explicitly bind the iterator prop to task-panel's prop:

                                     ?
<task-panel v-for="task in tasks" :task="task" />

Also, the prop in task-panel should have the same name. It's currently spelled tasks (with an s at the end). The last s should be removed so that it matches what the template is rendering:

// props: ['tasks', ?],
props: ['task', ?],

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<script src="https://cdn.tailwindcss.com"></script>

<div id="app">
    <task-input></task-input>
</div>

<script>
   let app =  Vue.createApp({  });

   app.component(
       'task-input',
       {
           template:
               `<div class=" container grid grid-cols-4 mb-5 border-2 border-gray-600 center  mt-5 mx-auto bg-gray-400 ">
                    <input id="taskInput"  v-model="task" class="bg-white col-span-3 p-3 text-black font-bold" type="text" placeholder="What you will do next" />
                    <button @click="addTask()"  class="text-white font-extrabold uppercase">Add new task</button>
                </div>
                <div class="container container mx-auto rounded-top-lg">
                    <div class=" bg-gray-200 border-2 border-gray-600 center column-1 container mx-auto mt-5 mx-auto rounded-top-lg">
                        <h1 class="font-sans text-2xl text-center text-white bg-gray-500  uppercase font-extrabold px-4 py-4">
                            {{title}}
                        </h1>
                        <ul class="bg-white">
                             <task-panel v-for="task in tasks" :task="task" />
                        </ul>
                     </div>
                </div>`,
               data() {
                   return {
                       title:"Here is a nice title",
                       task: '',
                       tasks: [],
                   }
            },
           components:['task-panel'],
           methods:{
               addTask(){
                   this.tasks.push(this.task);
                   this.task='';
                   console.log(this.tasks);
               }
           }
       },
   );

   app.component('task-panel',{
       template:
                `<li class="grid bg-gray-200 mt-1">
                    <div class="grid grid-cols-4">
                        <span class="col-span-3 bg-blue-200  p-2">{{task}}</span>
                        <span class="col-span-1 text-center self-center uppercase font-bold">test</span>
                    </div>
                    <div class="flex justify-end bg-gray-300 p-1">
                        <button class="bg-blue-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">To Do</button>
                        <button class="bg-green-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Done</button>
                        <button class="bg-red-500 text-white px-3 py-1 rounded-md m-1 uppercase font-bold">Blocked</button>
                    </div>
                </li>
                 `,
       data() {
           return {  }
       },
       props: ['task', 'modelValue'],
   });

   app.mount('#app');

</script>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tony19