Vue dynamic routes – display user details from another component

I have user list inside UserList.vue component. I would like to display each user details inside SigleUser.vue component (subpage). How can i do it the easy way?

User details is contained in the UserList.vue component. When I click on a link for a specific user, I would like to go to his profile

Router paths: /user/1, /user/2, /user/3 etc.

UserList.vue:

<template>
  <v-list two-line>
    <template v-for="(user) in users">
      <v-list-item
          :key="user.username"
      >
        <router-link
            :to="`user/${user.id}`"
        >
          <v-list-item-avatar>
            <v-img :src="user.avatar"></v-img>
          </v-list-item-avatar>
        </router-link>

        <v-list-item-content>
          <router-link
              :to="`user/${user.id}`"
          >
          <span class="name">
            {{ user.name }}
          </span>
            <span class="username">
            {{ user.usernaname }}
          </span>
          </router-link>
        </v-list-item-content>
      </v-list-item>
    </template>
  </v-list>
</template>

<script>
export default {
  data: () => ({
    users: [
      {
        id: 1,
        username: 'johndoe',
        name: 'John Doe',
        avatar: require('@/assets/images/john-doe.png'),
      },
      {
        id: 2,
        username: 'bobdoe',
        name: 'Bob Doe',
        avatar: require('@/assets/images/bob-doe.png'),
      },
      {
        id: 3,
        username: 'annedoe',
        name: 'Anne Doe',
        avatar: require('@/assets/images/anne-doe.png'),
      },
    ],

  }),
}
</script>

SingleUser.vue (Single user profile):

<template>
  <h1>{{ user.name }}</h1>
  <h2>{{ user.username }}</h2>
  <v-img :src="user.avatar"></v-img>
</template>

<script>

</script>

router.js:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
  path: '/',
  name: 'Home',
  component: Home
  },
  {
  path: '/users',
  name: 'Users',
  component: () => import('../views/UserList.vue')
  },

  {
  path: '/user/:id',
  name: 'User',
  component: () => import('../views/SingleUser.vue')
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

Answer

I created an example application in my Vue 2 CLI sandbox app. Normally I would retrieve users and user details from an API, but in my sample app, I used Vuex to store and retrieve users. I also used a standard <ul> instead of <v-list>, since I haven’t used Vuetify (another day), and left out the images. But the routing implementation should work in your application.

UserList.vue

<template>
  <div class="user-list">
    <h3>User List</h3>
    <div class="row">
      <div class="col-md-6">
        <ul>
          <li v-for="user in users" :key="user.id">
            <router-link :to="{ name: 'User', params: { id: user.id }}">{{ user.name }}</router-link>
          </li>
        </ul>
          </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'UserList',
    data() {
      return {
        users: [
          {
            id: 1,
            username: 'johndoe',
            name: 'John Doe',
          },
          {
            id: 2,
            username: 'bobdoe',
            name: 'Bob Doe',
          },
          {
            id: 3,
            username: 'annedoe',
            name: 'Anne Doe',
          },
        ]
      }
    },
    created() {
      this.$store.commit('initUsers', this.users);
    }
  }
</script>

SingleUser.vue

<template>
  <div class="single-user">
    <h3>Single User</h3>
    <div class="row">
      <div class="col-md-6">
        <h4>{{ user.name }}</h4>
        <h4>{{ user.username }}</h4>
        <router-link :to="{ name: 'Users' }">Back</router-link>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'SingleUser',
    props: {
      id: {
        type: Number,
        required: true
      }
    },
    computed: {
      user() {
        return this.$store.getters.getUser(this.id);
      }
    }
  }
</script>

/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import UserList from '@/components/stackoverflow/router-link/UserList'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/users'
  },
  {
    path: '/users',
    name: 'Users',
    component: UserList
  },
  {
    path: '/user/:id',
    name: 'User',
    component: () => import('@/components/stackoverflow/router-link/SingleUser'),
    props: true
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    users: []
  },
  getters: {
    getUser: (state) => (id) => {
      return state.users.find( user => user.id === id);
    }
  },
  mutations: {
    initUsers(state, newUsers) {
      state.users = newUsers;
    }
  }
})

Leave a Reply

Your email address will not be published. Required fields are marked *