Property or method (title,body) not defined

When redirecting to my edit component. i get that the title and body is not defined. When i press the update button i get 404 request and err connection timed out. My backend works fine without the front end i have tested to update.
My indexcomponent with all my post with an edit and button and delete button on each post.

    <template>
  <div>
    <h1>Posts</h1>
    <div class="row">
      <div class="col-md-10"></div>
      <div class="col-md-2">
        <router-link :to="{ name: 'create' }" class="btn btn-primary"
          >Create Post</router-link
        >
      </div>
    </div>
    <br />

    <table class="table table-hover">
      <thead>
        <tr>
          <th>Title</th>
          <th>Body</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <!-- Prints out every post in my list -->
        <tr v-for="post in allPosts" :key="post._id">
          <td>{{ post.title }}</td>
          <td>{{ post._id }}</td>
          <td>{{ post.body }}</td>

          <td>
            <!-- Links to my EditComponent -->
            <router-link
              :to="{ name: 'edit', params: { _id: post._id } }"
              class="btn btn-primary"
              >Edit</router-link
            >
          </td>
          <td>
            <!-- Should delete my post -->
            <button class="btn btn-danger" @click="deletePost(post._id)">
              Delete
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";
export default {
  name: "IndexComponent",
  // Actually no idea why this method is here, what should i put here?
  methods: {
    ...mapActions(["fetchPosts", "deletePost", "updatePost"]),

    // onDblClick(post) {
    //   const payload = {
    //     id: post.id,
    //     title: post.title,
    //     completed: !post.completed,
    //   };
    //   this.updPost(payload);
    // },
  },
  // COMPUTED - to define which getters to use..action to get
  computed: { ...mapGetters(["allPosts"]) },
  created() {
    this.fetchPosts();
  },
};
</script>

When pressing edit i get that title and body is not defined.

  <template>
  <div>
    <h1>Edit Post</h1>
    <form @submit.prevent="onDblClick">
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            <label>Post Title:</label>
            <input type="text" class="form-control" v-model="post.title" />
          </div>
          <td>[{{ post._id }}]</td>
        </div>
      </div>
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            <label>Post Body:</label>
            <textarea
              class="form-control"
              v-model="post.body"
              rows="5"
            ></textarea>
          </div>
        </div>
      </div>
      <br />
      <div class="form-group">
        <button class="btn btn-primary" type="submit">Update</button>
      </div>
    </form>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";
export default {
  name: "EditComponent",
  data() {
    return {
      post: {
        title: "",
        body: "",
      },
    };
  },
  methods: {
    ...mapActions(["fetchPosts", "updatePosts"]),

    onDblClick() {
      this.updatePosts({
        ...this.post,
        completed: false,
      });
    },

    // COMPUTED - to define which getters to use
    ...mapGetters(["getPost"]),
    created() {
      // Fetch post from vuex using id from route parameters
      const post = this.getPost(this.$route.params._id);

      // Make post available inside data
      this.post = post;
    },
  },
};
</script>
1 Like

When quoting an error message, please quote it exactly rather than paraphrasing. Otherwise we have to guess what the message actually said.

My best guess is that it is referring to this:

<input type="text" class="form-control" v-model="title" />

The v-model is trying to bind to a property of the instance called title but you haven’t defined a property with that name.

What you’ve defined is an instance property called post. That property has an object value and that object has properties called title and body.

So I would imagine you meant to write something like this:

<input type="text" class="form-control" v-model="post.title" />

As for the update button, the 404 suggests that you’re requesting the wrong URL. You haven’t included any of the code for your action but you can check what request it is making by looking in the Network tab of the browser’s developer tools. Compare the request you see there with whatever request you’re expecting. Presumably something is wrong otherwise it’d work. Then work back, using console logging if necessary, to establish why everything isn’t as expected.

The id is undefined. Maybe I should do like this? <input type="text" class="form-control" v-model="post.title :key=post.id" /> Here you have the code :

    // here should be added: state, getters, actions, mutations

import axios from "axios";

const state = {
  posts: [],
};

const getters = {
  allPosts: (state) => state.posts,
  getPost: (state) => (_id) => state.posts.find((e) => e._id === _id),
};

const actions = {
  //an action: makes a request, gets a response and calls a mutation
  async fetchPosts({ commit }) {
    // commit - to call the mutation
    const response = await axios.get("http://localhost:4000/posts");
    commit("setPost", response.data);
  },
  async addPost({ commit }, { title, body }) {
    const response = await axios.post("http://localhost:4000/posts/add", {
      title,
      body,
      completed: false,
    });
    console.log(title, body);
    commit("newPost", response.data);
  },
  async deletePost({ commit }, _id) {
    await axios.delete(`http://localhost:4000/posts/delete/${_id}`);
    commit("removePost", _id);
  },

  async updatePosts({ commit, state }, post) {
    // Find index of post

    const index = state.posts.findIndex((posts) => posts._id === post._id);

    // Return early here if post is not found in state
    if (index === -1) return;

    // Send api request
    await axios.post(`http://localhost:4000/posts/update/${post._id}`);

    console.log("response");

    // Commit changes in state
    commit("change", index, post);
  },
};

const mutations = {
  setPost: (state, posts) => (state.posts = posts),
  newPost: (state, posts) => state.posts.unshift(posts),
  removePost: (state, _id) =>
    (state.posts = state.posts.filter((post) => post._id !== _id)),
  change(state, index, payload) {
    state.posts[index] = payload;
  },
};

export default {
  state,
  getters,
  actions,
  mutations,
};

//this is a boilerplate for vuex module

And here is my errors:

1 Like

When you load the posts from the server using fetchPosts, do the posts actually have an id field?

All those warnings from vue-router seem to suggest that some of your posts, maybe all of your posts, don’t have an id.

Try dumping out the id in your template:

<td>{{ post.title }} [{{ post.id }}]</td>

No, I dont have any id field in my model class. I just let mongoose create a unique id for each post.

_id: 5fb396a6b6b599b4ecde6c0f,
title: ‘testone’,
body: ‘thebody’,
createdAt: 2020-11-17T09:23:50.124Z,
__v: 0

I got an empty space.

OK, so you’ll need to use _id instead of id everywhere that you’re using post.id in your code.

Yeah it is showing id in my index components but when i press edit i get this

also i have been following your advice about debugging. So i put {{post.id}}} in my edit component and it is not showing.

1 Like

But have you changed everything to use _id instead of id for the property name?

Putting {{post.id}} in the template isn’t going to show the id because it’s called _id. You’d need to use {{ post._id }}.

Likewise you need to change things in your store code. getPost is checking e.id, so that’ll need changing to e._id. updatePosts is doing a findIndex that matches on the id property. Again, that needs to be _id. Same in the axios URL.

You can still use the name id for a local variable but anywhere that tries to access the property on an object will need to use _id.

Yes everything works except the update. It does not pass consol.log(“beforeupdate”)

 async updatePosts({ commit, state }, post) {
        console.log("beforeupdate");
        // Find index of post

        const index = state.posts.findIndex((posts) => posts._id === post._id);
        console.log("a");

So you don’t see the logging from console.log("a")?

I don’t know why that would be. I’d either expect it to throw an error or reach that logging.

Sometimes when logging doesn’t show up it’s because the code in the browser is out of date. There are all sorts of reasons that might be.

If you take a look at the beforeupdate logging you’ll see it says post.js?ff1a:36 on the right-hand side. Click on that link to jump to the source code and check that it all looks how you’re expecting.

You could then try setting a breakpoint. If you haven’t seen breakpoints before then this may be a bit overwhelming at first. When you’re viewing the code in the browser (after following the link in the console), you can click in the margin to the left of the code and set a breakpoint. It should put something in the margin, maybe a blue line or dot (depends on your system). The next time it hits that line it’ll pause execution so you can see exactly what’s going on. You can then step through, one command at a time, to see exactly what happens. You’ll need to get used to the tools to take full advantage. There are plenty of resources online explaining more about how to use breakpoints and debugger statements.

I dont see a logging from my backend as i did 1 hour ago. Everytime I was going to update a post in my frontend i saw this console.log code from my server in my terminal. I will read more tomorrow and give you a more precise answer on what my error is so it gets easier for you to help me.

Okay I will read on it. I understand exactly what you mean but i will need to watch some videos to understand how i can use it to help me.

I have been looking for what could have gone wrong. 1. I get this error that

vue-router] missing param for named route “edit”: Expected “id” to be defined

  1. My code for update and delete could be wrong. Maybe i should create a false id? Edit: the backend works fine in postman. But everytime i get posts mongoose returns this wrapper in my terminal

     postRoutes.route("/update/:id").post(function (req, res) {
       console.log("upd");
       Post.findById(req.params.id, function (err, post) {
         console.log("update");
         if (!post) res.status(404).send("data is not found");
         else {
           post.title = req.body.title;
           post.body = req.body.body;
           console.log("updatebody");
           post
             .save()
             .then(() => {
               res.json("Update complete");
               console.log("update");
             })
             .catch(() => {
               res.status(400).send("unable to update the database");
             });
         }
       });
     });
    
     // Defined delete | remove | destroy route
     postRoutes.route("/delete/:id").delete(function (req, res) {
       console.log("del");
       Post.findByIdAndRemove({ _id: req.params.id }, function (err) {
         if (err) res.json(err);
         else res.json("Successfully removed");
         console.log("delete");
       });
     });
    
  2. I have also edited every code i posted here to the current code i have.

  3. When i press the update button i get no response at all. I have been checking network and console. I also put {{post.id}} in my edit component to se if it got printed out. But just this got printed out “[]”

The problem is this code in my backend. I should use map beacuse it is an array and post it as an object to json.

// Defined get data(index or listing) route
postRoutes.route("/").get(function (req, res) {
  console.log("getting");
  Post.find(function (err, posts) {
    if (err) {
      res.json(err);
    } else {
      res.json(posts);
      console.log(posts);
    }
  });
});