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

boyjarv's avatar

trying to pass props and edit a form Vue - what am I doing wrong?

in my todos.vue:

<AddEditForm
      :editing="this.editingTodo"
      :title="title"
      :description="description"
      :id="id"
    />

then in my AddEditForm component:



<script setup>
import { ssrRef, useRouter } from "@nuxtjs/composition-api";
import { useTodo } from "@/store/todos";
const router = useRouter();
const todo = useTodo();
const id = ssrRef("");
const title = ssrRef("");
const description = ssrRef("");

const addTodo = () => {
  if (!title.value || !description.value) {
    alert("Please fill all the field");
  } else {
    const data = {
      title: title.value,
      description: description.value,
    };
    todo.addTodo(data);
    todo.getTodos();
  }
};
const editThisTodo = () => {
  if (!title.value || !description.value) {
    alert("Please fill all the field");
  } else {
    const data = {
      id: id.value,
      title: title.value,
      description: description.value,
    };
    todo.editTodo(data);
    todo.getTodos();
  }
};
todo.getTodos();
</script>
<template>
  <div class="container my-10 mx-auto max-w-xl bg-purple-400 rounded-xl">
    <form action="" class="p-5" @submit.prevent="editThisTodo">
      <h1 class="text-white text-center text-3xl">
        {{ this.editing ? "Edit todo" : "Add todo" }}
        <div v-if="this.editing">
          {{ id }}
          {{ title }}
          {{ description }}
        </div>
      </h1>
      <div class="my-3">
        <label for="" class="text-md font-semibold"> Enter your title </label>
        <input type="hidden" name="id" v-if="id" v-model="id" />
        <input
          type="text"
          v-model="title"
          class="
            outline-none
            w-full
            py-2
            rounded
            bg-transparent
            border-b-2
            text-white text-lg
            placeholder-white
          "
          placeholder="Enter Your Title"
        />
      </div>
      <div class="my-3">
        <label for="" class="text-md font-semibold">
          Enter your description
        </label>
        <input
          type="text"
          v-model="description"
          class="
            outline-none
            w-full
            py-2
            rounded
            bg-transparent
            border-b-2
            text-white text-lg
            placeholder-white
          "
          placeholder="Enter Your Description"
        />
      </div>
      <button
        type="submit"
        class="
          rounded-md
          border
          px-10
          py-2
          bg-purple-600
          text-white text-xl text-semibold
          hover:bg-purple-700
        "
      >
        {{ useTodo.isloading ? "Todo...." : "Todo" }}
      </button>
    </form>
  </div>
</template>
<script>
export default {
  name: "AddEditTodo",
  props: {
    id: Number,
    editing: Boolean,
    todo: Object,
    title: String,
    description: String,
  },
  data() {
    return {
      selectedId: null,
      selectedTitle: "",
      selectedDescription: "",
    };
  },
  mounted() {
    this.selectedId = this.id;
    this.selectedTitle = this.title;
    this.selectedDescription = this.description;
    console.log("ID: ", this.selectedId);
  },
};
</script>
<style>
</style>

I have lots of errors, here's one:

[Vue warn]: Property or method "description" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

---> <TodosPage> at pages/admin/todos.vue
       <Nuxt>
         <.nuxt/layouts/default.vue> at .nuxt/layouts/default.vue
           <Root>
0 likes
5 replies
vincent15000's avatar

I haven't looked at all your code, but the first thing I've seen is this.

<AddEditForm
      :editing="this.editingTodo"
      :title="title"
      :description="description"
      :id="id"
    />

I would rather write this.

<AddEditForm
      :editing="editingTodo" // Here without this.
      :title="title"
      :description="description"
      :id="id"
    />
boyjarv's avatar

ok so I thought hmm, I actually have an API endpoint that points to a specific ID

So I created a new action in my store:

async getTodo(data) {
      this.isloading = true;
      console.log("Local storage: ", localStorage.getItem("token"));
      const res = await fetch("http://localhost:8000/api/todo/" + data.id, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + localStorage.getItem("token"),
        },
      });
      const output = await res.json();
      this.isloading = false;
      this.todo = output;
      // this.todos.push(output);
    },

and now my page looks like this:


<script setup>
import { ssrRef, useRouter } from "@nuxtjs/composition-api";
import { useTodo } from "@/store/todos";
const router = useRouter();
const todo = useTodo();
const id = ssrRef("");
const title = ssrRef("");
const description = ssrRef("");

const addTodo = () => {
  if (!title.value || !description.value) {
    alert("Please fill all the field");
  } else {
    const data = {
      title: title.value,
      description: description.value,
    };
    todo.addTodo(data);
    todo.getTodos();
  }
};
const editThisTodo = () => {
  if (!title.value || !description.value) {
    alert("Please fill all the field");
  } else {
    const data = {
      id: id.value,
      title: title.value,
      description: description.value,
    };
    todo.editTodo(data);
    todo.getTodos();
  }
};
todo.getTodos();
</script>
<template>
  <div class="container my-10 mx-auto max-w-xl bg-purple-400 rounded-xl">
    <form action="" class="p-5" @submit.prevent="editThisTodo">
      <h1 class="text-white text-center text-3xl">
        {{ this.editing ? "Edit todo" : "Add todo" }}
        <div v-if="this.editing">
          {{ id }}
          {{ title }}
          {{ description }}
        </div>
      </h1>
      <div class="my-3">
        <label for="" class="text-md font-semibold"> Enter your title </label>
        <input type="hidden" name="id" v-if="id" v-model="id" />
        <input
          type="text"
          v-model="title"
          class="
            outline-none
            w-full
            py-2
            rounded
            bg-transparent
            border-b-2
            text-white text-lg
            placeholder-white
          "
          placeholder="Enter Your Title"
        />
      </div>
      <div class="my-3">
        <label for="" class="text-md font-semibold">
          Enter your description
        </label>
        <input
          type="text"
          v-model="description"
          class="
            outline-none
            w-full
            py-2
            rounded
            bg-transparent
            border-b-2
            text-white text-lg
            placeholder-white
          "
          placeholder="Enter Your Description"
        />
      </div>
      <button
        type="submit"
        class="
          rounded-md
          border
          px-10
          py-2
          bg-purple-600
          text-white text-xl text-semibold
          hover:bg-purple-700
        "
      >
        {{ useTodo.isloading ? "Todo...." : "Todo" }}
      </button>
    </form>
  </div>
</template>
<script>
export default {
  name: "AddEditTodo1",
  props: {
    id: Number,
    editing: Boolean,
  },
  data() {
    return {
      selectedId: null,
      selectedTitle: "",
      selectedDescription: "",
    };
  },
  mounted() {
    this.selectedId = this.id;
    this.selectedTitle = this.title;
    this.selectedDescription = this.description;
    console.log("ID: ", this.selectedId);
  },
};
</script>
<style>
</style>

and the errors I am getting now are : Property or method "id" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

1 like
vincent15000's avatar

@boyjarv Can you show the view from where you call this component ? The id is a props, so you need to pass the value as a params to the component when you call it.

Something else : you should initialize this once at all in your code.

headers: {
  "Content-Type": "application/json",
  Authorization: "Bearer " + localStorage.getItem("token"),
},
boyjarv's avatar

I am passing it in params:

const res = await fetch("http://127.0.0.1:8000/api/todo/" + data.id, {
        method: "PUT",
        body: JSON.stringify(data),
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + localStorage.getItem("token"),
        },
      });
1 like
vincent15000's avatar

@boyjarv The id cannot be retrieved as a props in the component if you pass it as an URL parameter.

This way you need to retrieve the id in the route with the URLSearchParams() method.

If you want the id be automatically passed as a component parameter, you need to add it like this.

<my-component :id="id"></my-component>

Please or to participate in this conversation.