What is the best way to add an element from a parent component to an array within a child component in a Vue 3 application?

I am in the process of transitioning from Vue's Options API to the Composition API, and as part of this transition, I have built a small Todo App.

Within App.vue, my code looks like this:

<template>
  <div id="app">
    <div class="card">
      <Header />
      <List />
      <AddTodo @add-todo="addTodo" />
    </div>
  </div>
</template>

<script>
import { ref, onMounted, watch } from 'vue';
import Header from './components/Header.vue';
import List from './components/List.vue';
import AddTodo from './components/Add.vue';

export default {
  name: 'App',
  components: {
    Header,
    List,
    AddTodo,
  },

  methods: {
    addTodo: function (text) {
      let newTodo = {
        done: false,
        text: text,
      };

      if (text.length > 2) {
        console.log(newTodo);
        // this.todos.push(newTodo);
      }
    },
  },
};
</script>

In components/List.vue, you'll find:

<template>
  <ul>
    <Item
      v-for="(todo, index) in todos"
      @toggle-todo="toggleTodo(item, index)"
      @delete-todo="deleteTodo(item, index)"
      :item="todo"
      :key="index"
    />
  </ul>
</template>

<script>
import { ref, onMounted, watch } from 'vue';
import Item from './Item.vue';

export default {
  name: 'List',

  components: {
    Item,
  },

  setup() {
    const todos = ref([
      {
        text: 'Animi, odit facere.',
        done: true,
      },
      {
        text: 'Lorem ipsum dolor sit.',
        done: false,
      },
      {
        text: 'Dolor sit amet consectetur.',
        done: true,
      },
    ]);

    return { todos };
  },

  methods: {
    toggleTodo: function (item, index) {
      this.todos[index].done = !this.todos[index].done;
    },
    deleteTodo: function (item, index) {
      if (confirm('Are you sure?')) {
        this.todos.splice(index, 1);
      }
    },
  },
};
</script>

As shown above, I have defined the todos array within the list component, where it makes the most sense. The main purpose of App.vue is to act as a container for the other components.

Within components/Add.vue, I have created the form used to add an item to the list of todos.

<template>
  <form class="card-footer" @submit.prevent="$emit('add-todo', text)">
    <input type="text" v-model="text" />
    <button type="submit">Add</button>
  </form>
</template>

<script>
import { ref, onMounted, watch } from 'vue';
export default {
  name: 'AddTodo',

  setup() {
    const text = ref('');
    return { text };
  },
};
</script>

Since the todos array is not contained in App.vue, the line this.todos.push(newTodo), which I have commented out, will not work.

I am trying to figure out the best way to push the newTodo object into the todos array within the child component List.vue. Any suggestions on how to achieve this seamlessly?

Answer №1

Create a component List and define props named todos to bind it in the parent component:

<template>
  <div id="app">
    <div class="card">
      <Header />
      <List :todos="todos" @delete-todo="deleteTodo" @toggle-todo="toggleTodo" />
      <AddTodo @add-todo="addTodo" />
    </div>
  </div>
</template>

<script>
import { ref, onMounted, watch } from "vue";
import Header from "./components/Header.vue";
import List from "./components/List.vue";
import AddTodo from "./components/Add.vue";

export default {
  name: "App",
  components: {
    Header,
    List,
    AddTodo,
  },
  data() {
    return {
      isValid: false,
      todos: [
        {
          text: "Animi, odit facere.",
          done: true,
        },
        {
          text: "Lorem ipsum dolor sit.",
          done: false,
        },
        {
          text: "Dolor sit amet consectetur.",
          done: true,
        },
      ],
    };
  },
  methods: {
    toggleTodo: function ( index) {
      this.todos[index].done = !this.todos[index].done;
    },
    deleteTodo: function (index) {
      if (confirm("Are you sure?")) {
        this.todos.splice(index, 1);
      }
    },
    addTodo: function (text) {
      let newTodo = {
        done: false,
        text: text,
      };

      if (text.length > 2) {
        this.isValid = true;
        this.todos.push(newTodo);
      } else {
        this.isValid = false;
      }
    },
  },
};
</script>

In the List component, define todos props and emit events to modify the todos in the parent component:

<template>
  <ul>
    <Item
      v-for="(todo, index) in todos"
      @toggle-todo="toggleTodo( index)"
      @delete-todo="deleteTodo( index)"
      :item="todo"
      :key="index"
    />
  </ul>
</template>

<script>
import Item from './Item.vue';

export default {
  name: 'List',
  props:["todos"],
  components: {
    Item,
  },

  methods: {
    toggleTodo: function ( index) {
      this.$emit('toggle-todo',index);
    },
    deleteTodo: function ( index) {
      this.$emit('delete-todo', index);
    },
  },
};
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing jQuery for asynchronous image uploading

Just started learning jQuery and I'm having trouble uploading a jpg image file using the ajax method. It seems like it's not working properly. Can anyone guide me through this process? HTML <form action="" method="POST" enctype="multipart/fo ...

Invoke a jQuery function in the parent page using regular JavaScript from an iframe

I have successfully created an iframe using regular javascript. Inside the iframe is a Jquery function along with JQuery itself and it functions correctly within the iframe. However, I am now looking to execute this function from the parent page instead of ...

sending information from a PHP form to a JavaScript window

Currently, I am in the process of developing a game using javascript and jquery. In this game, when a player interacts with another character, it triggers the opening of text from an external file using the window.open('') function. At the start ...

Guide to creating AngularJS directive attributes without a right-hand side in hiccup code?

I'm currently developing an AngularJS application using markup in hiccup format. Here is a snippet of the markup: <div modal-show modal-visible="showDialog" .........></div> Below is the corresponding Hiccup I have created: [:div.modal. ...

Output JSON data from PHP for use in Javascript

Is there a way to effectively convert JSON data from PHP/Laravel into JSON for JavaScript? I have the JSON string from PHP, but it is only rendering as a string. How can I convert it to a JSON object in JavaScript? Take a look at my code below. $('#e ...

Ionic: How come my image is not loading with HTTP.GET?

I have been attempting to populate a gallery in my Ionic application by fetching images from a JSON file, but I am encountering issues. While following a guide on creating a grid-like image gallery using the Ionic framework (https://blog.nraboy.com/2015/03 ...

Tips on changing the outline color by clicking

I'm working on a simple code where I need to change the outline color when a user clicks on a text field. <input type="text" id="box1" /> <input type="password" id="box2" /> <input type="email" id="box3" /> <input type="submit" ...

An error was encountered while attempting to utilize Google's Core Reporting API: Uncaught SyntaxError: Unexpected token <

I've been experimenting with Google's Core Reporting API and successfully implemented their provided demo. Now, I'm trying to integrate the code into my own project. My main tech stack includes AngularJS and PHP. I aim to keep it simple by ...

Clicking on AngularJS ng-click to navigate to a different page within an Ionic framework application

My goal is to navigate to another page when clicking on a button in the Ionic navbar at the top. However, I am encountering an issue where upon clicking, all nav bar buttons disappear. Interestingly, using dummy codes triggers an alert successfully. But w ...

Integrating Facebook login with Cordova using the cordovaOauth plugin

Encountering issues while setting up FB login for my cordova mobile app. A tutorial followed: http://www.codeproject.com/Tips/1031475/How-to-Integrate-Facebook-Login-into-a-Cordova-App#_comments <script src="js/angular.js"></script> <scrip ...

What is the best way to designate external dependencies in WebPack that are not imported using '*'?

I need assistance with specifying office-ui-fabric-react as an external dependency in my TypeScript project using Webpack. Currently, I am importing only the modules I require in my project: import { Dialog, DialogType, DialogFooter } from 'office-u ...

Is there an Angular counterpart to Vue's <slot/> feature?

Illustration: Main component: <div> Greetings <slot/>! </div> Subordinate Component: <div> Planet </div> Application component: <Main> <Subordinate/> </Main> Result: Greetings Planet! ...

multiple server-side tables with toggle buttons

I'm struggling with a page that contains 3 tables using datatables. The issue is that datatables can't handle more than one table, and after searching for a solution, I found a customized SSP Datatables at this link: here However, I'm wonde ...

Implementing a Javascript solution to eliminate the # from a URL for seamless operation without #

I am currently using the pagepiling jQuery plugin for sliding pages with anchors and it is functioning perfectly. However, I would like to have it run without displaying the '#' in the URL when clicking on a link like this: www.mysite.com/#aboutm ...

trigger the focusout event within the focusin event

I am attempting to trigger the focusout event within the focusin event because I need to access the previous value from the focusin event, but the focusout event is being triggered multiple times. $('tr #edituser').focusin(function(){ var ...

Switching over to the latest version of Material-UI, v1.x.x

Currently, my app relies on Material-UI v0.17.0 which is not compatible with React v16.0.0. In order to make it work, I need to upgrade to Material-UI v1.0.0. I came across a migration tool here, but it only updates import statements. Many props have chan ...

Ways to access UserProfile in a different Dialogio

For the implementation of a chatbot, I am utilizing Microsoft's Bot Builder framework. However, upon implementing an alternative path to the dialog flow, I noticed that the user's Profile references are getting lost. Here is the code snippet fr ...

When integrating react-hook-form with Material-UI TextField in a form, an error occurs stating that "TypeError: e.target is undefined" when

Hey there, I stumbled upon something fascinating and could really use some assistance. Every time I attempt to perform an onChange, I run into the following error: TypeError: e.target is undefined. Here's a snippet of my setup: import React, { useE ...

Utilize Mongoose to seamlessly integrate online shopping cart items into MongoDB

I am facing an issue while trying to insert a shopping cart of items in the form of a JSON object into a MongoDB collection using a mongoose schema. Although the customer's ID is successfully stored (extracted from the User DB), unfortunately, the ca ...

Instructions on changing the color and font weight of an asterisk within a Textfield using Material UI

Is there a way to style the asterisk in red and bold within a Textfield using material UI? I have a placeholder text without a label, as my label is null or empty. I would like to make the placeholder star RED. Is this possible? Here is the code snippet: h ...