Meidanm
Meidanm

Reputation: 31

VUE JS router link wrong path

I am new to vue and I am working on a project to fetch wordpress REST api. so I have "Posts" page and "Pages" page in my project, each one of them has different api endpoint and router links to every post/page in the loop with the slug name of the specific post/page.

When I press on the READ MORE router link button inside "Posts" page it sends me to the "Post" component with the post endpoint. When I press on the READ MORE router link button inside Pages page it also sends me to the "Post" component but I need to get the "Page" component to fetch the page data from the api.

I noticed that if I set the page component before the post component inside index.js so both Posts and Pages will open the page component.

How can I set the "Page" component to the "Pages" router link and the "Post" component to "Posts" router link?

index.js:

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/posts',
    name: 'Posts',
    component: () => import(/* webpackChunkName: "posts" */ '../views/Posts.vue')
  },
  { 
    path: '/pages',
    name: 'Pages',
    component: () => import(/* webpackChunkName: "pages" */ '../views/Pages.vue')
  },
  {
    path: '/:pageSlug',
    name: 'Page',
    component: () => import(/* webpackChunkName: "page" */ '../components/Page/Page.vue')
  },
  {
    path: '/:postSlug',
    name: 'Post',
    component: () => import(/* webpackChunkName: "post" */ '../components/Post/Post.vue')
  },
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

router.afterEach((to) => { // (to, from)
  // Add a body class specific to the route we're viewing
  let body = document.querySelector('body');

  const slug = !(to.params.postSlug)
    ? to.params.pageSlug
    : to.params.postSlug;
  body.classList.add('vue--page--' + slug);
});


export default router

Pages.vue:

<template>
<div>
<template v-if="pages">
<div class="pages">
    <div class="row">
      <div class="column" v-for="(page, index) in pages" :key="index">
        <div class="card">
          <div class="card-image">
            <img
              v-if="page._embedded['wp:featuredmedia']"
              :src="page._embedded['wp:featuredmedia'][0].source_url"
            />
          </div>
          <div class="card-content" v-html="page.excerpt.rendered"></div>
          <div class="card-action">
            <h3>{{ page.title.rendered }}</h3>
          </div>
        </div>
                <router-link :to="page.slug" tag="div" key="page.id">
READ MORE </router-link> //this is where I think the problem is..
      </div>
    </div>
    </div>
  </template>
  <div id="loaded" v-else>Loading...</div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data() {
    return {
      // Wordpress Pages Endpoint
      postsUrl: "https://my-domain.com/wp-json/wp/v2/pages",
      queryOptions: {
        per_page: 6, // Only retrieve the 6 most recent blog pages.
        page: 1, // Current page of the collection.
        _embed: true //Response should include embedded resources.
      },
      // Returned Pages in an Array
      pages: []
    };
  },
  methods: {
    // Get Recent Pages From WordPress Site
    getRecentMessages() {
      axios
        .get(this.postsUrl, { params: this.queryOptions })
        .then(response => {
          this.pages = response.data;
          console.log("Pages retrieved!");
          console.log(this.pages);
        })
        .catch(error => {
          console.log(error);
        });
    },
  },
  mounted() {
    this.getRecentMessages();
  }
};
</script>

Posts.vue:

<template>
<div>
<template v-if="posts">
<div class="posts">
    <div class="row">
      <div class="column" v-for="(post, index) in post" :key="index">
        <div class="card">
          <div class="card-image">
            <img
              v-if="post._embedded['wp:featuredmedia']"
              :src="post._embedded['wp:featuredmedia'][0].source_url"
            />
          </div>
          <div class="card-content" v-html="post.excerpt.rendered"></div>
          <div class="card-action">
            <h3>{{ post.title.rendered }}</h3>
          </div>
        </div>
                <router-link :to="post.slug" tag="div" key="post.id">
READ MORE </router-link>
      </div>
    </div>
    </div>
  </template>
  <div id="loaded" v-else>Loading...</div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data() {
    return {
      // Wordpress Posts Endpoint
      postsUrl: "https://my-domain.com/wp-json/wp/v2/posts",
      queryOptions: {
        per_page: 6, // Only retrieve the 6 most recent blog posts.
        page: 1, // Current page of the collection.
        _embed: true //Response should include embedded resources.
      },
      // Returned Posts in an Array
      posts: []
    };
  },
  methods: {
    // Get Recent Posts From WordPress Site
    getRecentMessages() {
      axios
        .get(this.postsUrl, { params: this.queryOptions })
        .then(response => {
          this.posts= response.data;
          console.log("Posts retrieved!");
          console.log(this.posts);
        })
        .catch(error => {
          console.log(error);
        });
    },
  },
  mounted() {
    this.getRecentMessages();
  }
};
</script>

Upvotes: 0

Views: 1040

Answers (1)

Meidanm
Meidanm

Reputation: 31

OK So based on documentation here: https://router.vuejs.org/guide/essentials/named-routes.html I just changed the router links in "Posts" and "Pages" components to piont to their specific component for Posts.vue

You need to change :

<router-link :to="post.slug" tag="div" key="post.id">READ MORE </router-link>

With:

<router-link :to="{ name: 'Post', params: { postSlug: post.slug }}">READ MORE </router-link>

And the same for Pages.vue:

<router-link :to="{ name: 'Page', params: { pageSlug: page.slug }}">READ MORE </router-link>

Upvotes: 1

Related Questions