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

CamKem's avatar
Level 10

Help with submitting form using Vue & Pinia store action

Hello, I have created a form (inside a modal) that submits to a action inside of a Pinia store. I can get the action to trigger, but these is something wrong with the way I have coded this. This is the code from my TeamStore.js

export let useTeamStore = defineStore("team", {
    state: () => ({
            name: '',
            max: 1,
            avatar: '',
            members: [],
        }),
    actions: {
        // async will only fill the store once the view is mounted & the action is called
        async fill() {
            let data = await import('@/team.json');
            this.$state = data.default;
        },

        addSpots(number) {
            this.max += number;
            flashMessage('The team size is increased', 'success');
        },

        createMember(name, email, status) {
            console.log('createMember', name, email, status);
            if (this.members.length === this.max) {
                flashMessage('The team is full', 'error');
            } else {
                // work out what the next id is
                let ids = this.members.map((m) => m.id);
                let max = Math.max(...ids);
                let member = {};
                // create the member
                member.id = max + 1;
                member.name = name;
                member.email = email;
                member.status = status;
                member.avatar = `https://api.adorable.io/avatars/285/${member.email}.png`;
                this.members.push(member);

                flashMessage('The team member is added', 'success');
            }
        },

        readMember(id) {
            return this.members.find((m) => m.id === id);
        },
        updateMember(id, data) {
            // find the member in the array
            let member = this.members.find((m) => m.id === id);
            // update the member
            member.name = data.name;
            member.email = data.email;
            member.avatar = data.avatar;

            flashMessage('The team member is updated', 'success');
        }
        ,
        deleteMember(id) {
            // remove the member from the array
            let index = this.members.findIndex((m) => m.id === id);
            this.members.splice(index, 1);

            flashMessage('The team member is deleted', 'error');
        },
    },
    getters: {
        spotsRemaining() {
            return this.max - this.members.length;
        },
    }
});

This is the code for where the form is rendered.

  <Modal :show="showModal" @close="showModal = false">
    <template #default>
      <h2 class="text-2xl font-bold mb-2">Add a new member</h2>
      <form class="flex flex-col gap-y-4" @submit="team.createMember()">
        <div class="flex flex-col gap-y-1">
          <label for="name" class="text-lg font-medium">Name</label>
          <input type="text" id="name" class="border border-gray-300 px-4 py-2 rounded" />
        </div>
        <div class="flex flex-col gap-y-1">
          <label for="email" class="text-lg font-medium">Email</label>
          <input type="email" id="email" class="border border-gray-300 px-4 py-2 rounded" />
        </div>
        <div class="flex flex-col gap-y-1">
          <label for="status" class="text-lg font-medium">Status</label>
          <select id="status" class="border border-gray-300 px-4 py-2 rounded">
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
          </select>
        </div>
        <button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Add Member</button>
      </form>
    </template>
  </Modal>

When I console.log(name, email, status) in the createMember action, I get undefined, undefined, undefined. So know that the values are not getting passed through to the action.

Can you help me fix the code so that when the form is submitted, the values that are entered into the form are passed into the createMember() action & the store is updated so that the new member is added to the array.

Thanks in advance for your assistance!

EDIT: the team member is being added, but as the console log shows, its Undefined, Undefined, Undefined.

0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

The issue is that the form data is not being passed to the createMember action. To fix this, you need to bind the form inputs to data properties and pass them as arguments to the createMember action. Here's how you can modify the code:

  1. Add data properties for the form inputs in the component:
data() {
  return {
    name: '',
    email: '',
    status: 'active',
  };
},
  1. Bind the form inputs to the data properties using v-model:
<input type="text" id="name" class="border border-gray-300 px-4 py-2 rounded" v-model="name" />
<input type="email" id="email" class="border border-gray-300 px-4 py-2 rounded" v-model="email" />
<select id="status" class="border border-gray-300 px-4 py-2 rounded" v-model="status">
  <option value="active">Active</option>
  <option value="inactive">Inactive</option>
</select>
  1. Pass the data properties as arguments to the createMember action:
<form class="flex flex-col gap-y-4" @submit.prevent="team.createMember(name, email, status)">

Note that we're using @submit.prevent to prevent the default form submission behavior and passing the data properties as arguments to the createMember action.

Here's the modified code for the component:

<template>
  <Modal :show="showModal" @close="showModal = false">
    <template #default>
      <h2 class="text-2xl font-bold mb-2">Add a new member</h2>
      <form class="flex flex-col gap-y-4" @submit.prevent="team.createMember(name, email, status)">
        <div class="flex flex-col gap-y-1">
          <label for="name" class="text-lg font-medium">Name</label>
          <input type="text" id="name" class="border border-gray-300 px-4 py-2 rounded" v-model="name" />
        </div>
        <div class="flex flex-col gap-y-1">
          <label for="email" class="text-lg font-medium">Email</label>
          <input type="email" id="email" class="border border-gray-300 px-4 py-2 rounded" v-model="email" />
        </div>
        <div class="flex flex-col gap-y-1">
          <label for="status" class="text-lg font-medium">Status</label>
          <select id="status" class="border border-gray-300 px-4 py-2 rounded" v-model="status">
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
          </select>
        </div>
        <button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Add Member</button>
      </form>
    </template>
  </Modal>
</template>

<script>
export default {
  data() {
    return {
      name: '',
      email: '',
      status: 'active',
    };
  },
  props: {
    showModal: Boolean,
  },
  inject: ['team'],
};
</script>

And here's the modified code for the TeamStore.js:

export let useTeamStore = defineStore("team", {
  state: () => ({
    name: "",
    max: 1,
    avatar: "",
    members: [],
  }),
  actions: {
    // async will only fill the store once the view is mounted & the action is called
    async fill() {
      let data = await import("@/team.json");
      this.$state = data.default;
    },

    addSpots(number) {
      this.max += number;
      flashMessage("The team size is increased", "success");
    },

    createMember(name, email, status) {
      console.log("createMember", name, email, status);
      if (this.members.length === this.max) {
        flashMessage("The team is full", "error");
      } else {
        // work out what the next id is
        let ids = this.members.map((m) => m.id);
        let max = Math.max(...ids);
        let member = {};
        // create the member
        member.id = max + 1;
        member.name = name;
        member.email = email;
        member.status = status;
        member.avatar = `https://api.adorable.io/avatars/285/${member.email}.png`;
        this.members.push(member);

        flashMessage("The team member is
jayel74's avatar

How about updating an member? And canceling the update? I am struggeling the whole day with this problem.

Please or to participate in this conversation.