If you're using an event bus, emit the event:
Event.$emit("addItem", payload);
then handle the emitted event:
Event.$on('addItem', function (payload) {
// add payload to list of todos
});
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
ok so my Remove method works when I remove an item from my list but how can I add an item to the list?
methods: {
removeTodo(index) {
this.list.splice(index, 1);
},
addTodo(index) {},
},
here is where I'm calling the Todos
<Todo
v-if="type == 'todo'"
:todoDetails="item"
data-item="todo"
@remove="removeTodo(index)"
@added="addTodo(index)"
/>
If you're using an event bus, emit the event:
Event.$emit("addItem", payload);
then handle the emitted event:
Event.$on('addItem', function (payload) {
// add payload to list of todos
});
Can anyone help here please?
Why are you passing an index, you should pass the content of the new todo.
addTodo(newTodo) {
this.list.push(newTodo);
},
When emitting added event do this:
$emit('added', newTodo);
Then handle it:
<Todo
@added="(newTodo) => addTodo(newTodo)"
/>
here is my AddTodoForm.vue axios post (child):
<template>
<div class="flex flex-col w-100">
<form @submit.prevent="onAddTodo" class="flex flex-col">
<BaseInput
v-model="todo.title"
label="Title"
type="text"
class="border-2 p-2 rounded mb-4"
/>
<BaseInput
v-model="todo.description"
label="Description"
type="text"
class="border-2 p-2 rounded mb-4"
/>
<AppButton
type="submit"
class="rounded border-2 border-gray p-2"
@click="$emit('close')"
>
<div>Add Todo</div>
</AppButton>
</form>
</div>
</template>
<script>
import Swal from "sweetalert2";
import axios from "axios";
import AppButton from "@/components/AppButton.vue";
import BaseInput from "@/components/BaseInput.vue";
export default {
name: "AddTodoForm",
components: {
AppButton,
BaseInput,
},
data() {
return {
todo: {
title: "",
description: "",
},
alertShow: false,
alertClasses: "",
alertText: "",
};
},
methods: {
clearFields() {
this.title = "";
this.description = "";
},
onAddTodo() {
this.todo = {
title: this.todo.title,
description: this.todo.description,
};
try {
axios.post("todo", this.todo).then(() => {
this.$emit("added", this.todo);
this.clearFields();
Swal.fire({
title: `Successfully added`,
text: ` ${this.todo.title} has been added!`,
icon: "success",
buttons: true,
dangerMode: false,
});
this.clearFields();
});
} catch (error) {
console.log("ERROR: ", error);
}
},
},
};
</script>
this is my List Items (parent):
<template>
<!-- Company List -->
<ul class="flex flex-wrap justify-between">
<li
class="max-w-160 w-full mx-4 md:mx-0 md:w-1/3"
v-for="(item, index) in list"
:key="item.id"
data-item="item"
>
<Company
v-if="type == 'company'"
:companyDetails="item"
data-item="company"
@remove="remove(index)"
/>
<Contact
v-if="type == 'contact'"
:contactDetails="item"
data-item="contact"
@remove="remove(index)"
/>
<Todo
v-if="type == 'todo'"
:todoDetails="item"
data-item="todo"
@remove="remove(index)"
@added="(newTodo) => addTodo(newTodo)"
/>
<Artwork
v-if="type == 'artwork'"
:artworkDetails="item"
data-item="artwork"
/>
</li>
</ul>
</template>
<script>
import Company from "@/components/company/Company.vue";
import Contact from "@/components/contact/Contact.vue";
import Todo from "@/components/todo/Todo.vue";
import Artwork from "@/components/gallery/Artwork.vue";
export default {
components: {
Company,
Contact,
Todo,
Artwork,
},
props: {
listItems: [],
type: {
type: String,
},
},
data() {
return {
list: [],
};
},
mounted() {
this.list = this.listItems;
},
methods: {
remove(index) {
this.list.splice(index, 1);
},
addTodo(newTodo) {
console.log("newTodo: ", newTodo);
this.list.push(newTodo);
},
},
};
</script>
it's still not adding to my list?!
still not working, can anyone help please?
@boyjarv a few questions/observations. What does the console.log return in the addTodo method? I.e. is the new todo showing in the log?
Second, why are you setting this.todo in the onAddTodo method? Aren't you just setting it with the values that it already has?
Third, clear fields seems to be doing nothing. There is no this.title and this.description to clear.
Fourth, what does the close emit event do on the submit button? Could this be conflicting? Maybe emit this event after the axios post request has returned in the onAddTodo method?
@ben taylor It's not getting to the console log on the addTodo method
Second, why are you setting this.todo in the onAddTodo method? I was just following instructions from further up in this topic
Third, clear fields seems to be doing nothing. There is no this.title and this.description to clear. - Thank you, I changed to:
clearFields() {
this.todo.title = "";
this.todo.description = "";
},
Fourth, what does the close emit event do on the submit button? Could this be conflicting? Maybe emit this event after the axios post request has returned in the onAddTodo method? Close is closing the modal that contains the form, I have changed the axios call now:
axios.post("todo", this.todo).then(() => {
Swal.fire({
title: `Successfully added`,
text: ` ${this.todo.title} has been added!`,
icon: "success",
buttons: true,
dangerMode: false,
});
this.clearFields();
this.$emit("added", this.todo);
});
ok still not getting into the addTodo method in this page:
<template>
<div>
<div v-if="!isLoading" class="container max-w-6xl mx-auto my-20">
<div class="flex justify-between mx-8 md:mx-4 mb-4">
<h2 v-show="!isLoading" class="text-4xl text-center">Todos</h2>
<AppButton
type="secondary"
:processing="isLoading"
@click.prevent="isOpen = true"
>
Add New Todo
</AppButton>
</div>
<ListItems
:listItems="todos.data"
type="todo"
@added="(newTodo) => addTodo(newTodo)"
/>
<Pagination
class="w-80 md:w-auto"
:data="todos"
@pagination-change-page="getPaginatedTodos"
>
<template #prev-nav>
<span>< Previous</span>
</template>
<template #next-nav>
<span>Next ></span>
</template>
</Pagination>
<ModalWindow :open="isOpen" @close="closeModal()">
<AddTodoForm @close="closeModal()" />
</ModalWindow>
</div>
</div>
</template>
<script>
import { ref } from "vue";
import axios from "axios";
import AppButton from "@/components/AppButton.vue";
import ListItems from "@/components/ListItems.vue";
import LaravelVuePagination from "laravel-vue-pagination";
import ModalWindow from "@/components/ModalWindow.vue";
import AddTodoForm from "@/components/todo/AddTodoForm.vue";
import { mapGetters } from "vuex";
import { GET_USER_TOKEN_GETTER } from "@/store/storeconstants";
export default {
name: "TodoView",
components: {
AppButton,
AddTodoForm,
ListItems,
Pagination: LaravelVuePagination,
ModalWindow,
},
computed: {
...mapGetters("auth", {
token: GET_USER_TOKEN_GETTER,
}),
},
data() {
return {
isLoading: false,
todos: [],
links: [],
isOpen: ref(false),
pagination: {
current_page: 1,
},
};
},
methods: {
async getPaginatedTodos(pageNo = 1) {
this.isLoading = true;
let response = await axios.get(
`todos?page=${pageNo}`,
"Bearer: " + this.token
);
try {
this.todos = response.data;
this.links = response.data.links;
this.pagination = response.data.links;
this.isLoading = false;
} catch (error) {
console.log("Error: ", error);
}
},
closeModal() {
this.isOpen = !this.isOpen;
},
addTodo(newTodo) {
console.log("newTodo: ", this.newTodo);
this.todos.push(newTodo);
},
},
mounted() {
this.getPaginatedTodos();
},
};
</script>
should I be using
watch() { }
?
or should I just setup and use STATE?
Ok, couple more things. You should clear the todo after you emit the added event, otherwise you are emitting an empty todo.
In your console.log you are logging this.newTodo. remove the 'this.' part. Then tell me if it is logging anything.
ok clearing after my emit now and I removed 'this' in the console log
I have tried this in my ListItems.vue and in Todo.vue
addTodo(newTodo) {
console.log("newTodo: ", newTodo);
this.todos.push(newTodo);
},
neither work nothing gets logged to the console
Ok, let's make sure the axios request is returning success and the code in the then clause is firing. Chuck a console.log statement in there and see what you get. Also for the time being, try commenting out everything in the then clause accept for the emit.
Also, I'm not sure why you are importing and using ref from Vue when you are using the options api?
ok on my similar post someone suggested adding the emit on the AdTodoForm and the method and listener on the TodoView...
So I am now being able to emit it and listen but now I'm getting:
TypeError: this.todos.push is not a function
I think that is because my todo I am passing in is an object but I'm not sure how to fix:
updateTodoList(todo) {
console.log("TODO: ", todo);
this.todos.push([todo]);
},
I just fixed it, using :
updateTodoList(todo) {
this.todos.data.push({ ...todo });
},
Please or to participate in this conversation.