Vue Final Project - Part 2 - Getting Started on the UI Components

In this step we'll begin to create the user interface (UI) components for the project.

Create the UserList View

Create a file named UserList.vue in the views folder - for now just put this code in it:

<template>
    <h1>Users</h1>
</template>

Update the router file (note that the router file is index.js in the router folder):

  1. Import the UsersList.vue component:
import UserList from '../views/UserList.vue'
  1. Add an object to the routes array, the path should be users/, the name of the route should be UserList and the component should be the UserList component that we just imported. Here's what the code should look like:
{ path: '/users', name: 'UserList', component: UserList }

Now, in App.vue add a router-link element that navigates to the route with the name of UserList:

<router-link :to="{name: 'UserList'}">Users</router-link>

Run the app and click on the Users* link. It should navigate to the UserList component. The UserList component doesn't do much right now (but at least we know we can navigate to it). Next we'll set it up to fetch users from the JSON server.

Setup the UserList View to Get All Users

Replace the code in UserList.vue with this:

<template>
    <div class="user-list">
        <table border="1">
            <tr>
                <th>User</th>
                <th>Email</th>
                <th>Role</th>
                <th>Active</th>
                <th></th>
            </tr>
            <tr v-for="u in users" :key="u.id">
                <td>{{u.firstName + " " + u.lastName}}</td>
                <td>{{u.email}}</td>
                <td>{{getRoleNameById(u.roleId)}}</td>
                <td>{{u.active ? "yes" : "no"}}</td>
                <td>
                    <button @click="editUser(u.id)">Edit</button>
                </td>
            </tr>
        </table>
    </div>
</template>

<script>
import {getAllUsers, getAllRoles} from "@/api"

export default {
    data(){
        return {
            users: [],
            roles:[]
        }
    },
    mounted(){
        getAllUsers().then(users => this.users = users);
        getAllRoles().then(roles => this.roles = roles);
    },
    methods:{
        getRoleNameById(id){
          const role = this.roles.find(r => r.id == id);
          return role?.name;
          // Note the nullish operator - I noticed that this method gets called even before the roles have been fetched! 
        },
        editUser(id){
            console.log("TODO: edit user " + id);
        }
    }
}
</script>

<style scoped>
  /*Put CSS styles here*/
</style>

Notes:

  1. When the component is mounted, we call the getAllUsers() function, which we imported from the api.js file/module. Once we have fetched the users, we assign them to the users data member. Likewise, we fetch all user roles from the server, this allows us to display the role name, rather than the roleId (which means nothing to our end users).
  2. We use the v-for directive to loop through the users data member and create a row for each user.
  3. Each row includes a button, which when clicked will trigger the editUser() method and pass the appropriate user id to it. Right now the editUser() method simply does a console log, but soon we'll update it to redirect to a view that will allow you to edit the user settings

Make sure you run the app and click on the button(s), and verify that the console log is showing the proper user id.

REMINDER: You will need to Bootstrap the table (and make sure to make use of icons). This is something that you've done already in Int Web Dev

Create the User Details View

Create a file named UserDetails.vue in the views folder, put this code in it:

<template>
  <h1>UserDetails {{userId}}</h1>
</template>

<script>
export default {
    props:["userId"]
}
</script>

Note that it takes a prop named userId, which will eventually get passed in from the router. The userId is being displayed in the template of the component.

In the router file (router/index.js), import the UserDetails component:

import UserDetails from '../views/UserDetails.vue'

And then add this 'route' object to the routes array:

{ path: '/users/:userId', name: 'UserDetails', component: UserDetails, props: true }

Notes:

  1. The path includes a variable in the url named :userId. This is a placeholder for the id of the user that will be displayed in the UserDetails view. So if the actual requested path is users/7, then the userId variable would be set to 7.
  2. Note that the props is set to true, which means that this route will pass the userId variable as a prop into the UserDetails component.

We haven't set up a way for our app to navigate to the UserDetails component yet, but you can try it out by running the app and then navigating to http://localhost:8080/users/1 (it's possible that your app is running on a different port, so you have to use that port number rather than 8080).

Now we'll add code in the UserList component that will programatically navigate to the UserDetails component. Update the editUser() method in UserList.vue to look like this:

editUser(id){
    this.$router.push({name:'UserDetails', params: {userId:id}});
}

Notes:

  1. You can access the router from inside a component with this.$router. And you can call it's push() method to navigate to a route.
  2. The params property allows you to set route variables.

Run the app and click on a button in the UserList. You should see the UserDetails component with the proper user id on display.

Hopefully you are understanding how the components and the router are working together. I've tried hard to keep things simple (baby steps is the key!), but as you'll see in the next step, the UserDetails component will get more complicated.