Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

boyjarv's avatar

add item to a list and show it has been added using emit?

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)"
      />
0 likes
18 replies
lbecket's avatar

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  
});
lbecket's avatar

@boyjarv If you add window.Event = new Vue(); to app.js (or wherever you're registering Vue), then you can use the method I described above.

MohamedTammam's avatar

Why are you passing an index, you should pass the content of the new todo.

addTodo(newTodo) {
	this.list.push(newTodo);
},
Niush's avatar

When emitting added event do this:

$emit('added', newTodo);

Then handle it:

<Todo
    @added="(newTodo) => addTodo(newTodo)"
/>
boyjarv's avatar

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?!

boyjarv's avatar

still not working, can anyone help please?

Ben Taylor's avatar

@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?

boyjarv's avatar

@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>&lt;&nbsp;Previous</span>
        </template>
        <template #next-nav>
          <span>Next&nbsp;&gt;</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>

boyjarv's avatar

or should I just setup and use STATE?

Ben Taylor's avatar

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.

boyjarv's avatar

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

Ben Taylor's avatar

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?

boyjarv's avatar

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]);
    },
boyjarv's avatar

I just fixed it, using :

updateTodoList(todo) {
      this.todos.data.push({ ...todo });
    },

Please or to participate in this conversation.