Contents
Hi there, today we will show you how to develop login and registration in Vue.js app using API. Most of the web apps today that have users or different types of users require login or authentication to safeguard the functionalities and data information of the system. And today, I will show you how to make a user login and registration in Vue.js.
Vue JS also called vue.js is an open-source JavaScript library used for building user interfaces(UI). It is one of the most popular JavaScript libraries for building the front end.
In this tutorial, we will be using the API available that is made by Binaryboxtus. you can check it out here.
Prerequisite:
- node >= v16.10.0
- @vue/cli
Step 1: Create A Vue.js Project
First, select a folder that you want the Vue.js project to be created then execute this command on Terminal or CMD :
vue create vue-login-register
Step 2: Install packages
After creating a fresh vue.js project, go to the vue.js project folder and install these packages:
- vue-router – a package used for routing and the official router for vue.js
- bootstrap – a package of bootstrap framework
- axios – a promised-based HTTP library that is used to request to a server or API.
npm i bootstrap
npm i vue-router
npm i axios
Step 3: Create .env
After installing the packages, we will now create our .env file on our root directory. We will declare the API base URL and API Key in the .env file. Don’t forget to add it to the .gitignore file.
You can get the VUE_APP_API_KEY here. Click the “Reveal Key” button and copy the API key.
.env
VUE_APP_API_URL="https://mock-api.binaryboxtuts.com/"
VUE_APP_API_KEY="put_the_api_key_here"
Step 4: Routing and Components
We will now create the component, refer to the image below for the file structure.
You can create your own file structure but for this tutorial just follow along.
Let’s update the main.js file – We will add the axios base URL and add the API Key on the axios header.
src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import { createRouter, createWebHistory } from 'vue-router';
import LoginPage from './components/pages/LoginPage';
import RegisterPage from './components/pages/RegisterPage';
import DashboardPage from './components/pages/DashboardPage';
axios.defaults.baseURL = process.env.VUE_APP_API_URL
axios.interceptors.request.use(function (config) {
config.headers['X-Binarybox-Api-Key'] = process.env.VUE_APP_API_KEY;
return config;
});
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: LoginPage },
{ path: '/register', component: RegisterPage },
{ path: '/dashboard', component: DashboardPage },
],
});
createApp(App).use(router).mount('#app');
Let’s update the App.vue file – Let’s change all the code in it:
src/App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
Let’s create a file named LayoutDiv.vue – this will serve as a template.
src/components/LayoutDiv.vue
<template>
<div class="container">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'LayoutDiv',
};
</script>
We will now create a directory src/components/pages. Inside the folder let’s create these files for our pages:
- DashboardPage.vue
- LoginPage.vue
- RegisterPage.vue
src/components/pages/DashboardPage.vue
<template>
<layout-div>
<div class="row justify-content-md-center">
<div class="col-12">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Dashboard</a>
<div class="d-flex">
<ul class="navbar-nav">
<li class="nav-item">
<a @click="logoutAction()" class="nav-link " aria-current="page" href="#">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<h2 class="text-center mt-5">Welcome, {{user?.name}}!</h2 >
</div>
</div>
</layout-div>
</template>
<script>
import axios from 'axios';
import LayoutDiv from '../LayoutDiv.vue';
export default {
name: 'DashboardPage',
components: {
LayoutDiv,
},
data() {
return {
user: {},
};
},
created() {
this.getUser();
if(localStorage.getItem('token') == "" || localStorage.getItem('token') == null){
this.$router.push('/')
}else {
this.getUser();
}
},
methods: {
getUser() {
axios.get('/api/user', { headers:{Authorization: 'Bearer ' + localStorage.getItem('token')}})
.then((r) => {
this.user = r.data;
return r
})
.catch((e) => {
return e
});
},
logoutAction () {
axios.post('/api/logout',{}, { headers:{Authorization: 'Bearer ' + localStorage.getItem('token')}})
.then((r) => {
localStorage.setItem('token', "")
this.$router.push('/')
return r
})
.catch((e) => {
return e
});
}
},
};
</script>
src/components/pages/LoginPage.vue
<template>
<layout-div>
<div class="row justify-content-md-center mt-5">
<div class="col-4">
<div class="card">
<div class="card-body">
<h5 class="card-title mb-4">Sign In</h5>
<form>
<p v-if="Object.keys(validationErrors).length != 0" class='text-center '><small class='text-danger'>Incorrect Email or Password</small></p>
<div class="mb-3">
<label
htmlFor="email"
class="form-label">
Email address
</label>
<input
v-model="email"
type="email"
class="form-control"
id="email"
name="email"
/>
</div>
<div class="mb-3">
<label
htmlFor="password"
class="form-label">Password
</label>
<input
v-model="password"
type="password"
class="form-control"
id="password"
name="password"
/>
</div>
<div class="d-grid gap-2">
<button
:disabled="isSubmitting"
@click="loginAction()"
type="button"
class="btn btn-primary btn-block">Login</button>
<p class="text-center">Don't have account?
<router-link to="/register">Register here </router-link>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
</layout-div>
</template>
<script>
import axios from 'axios';
import LayoutDiv from '../LayoutDiv.vue';
export default {
name: 'LoginPage',
components: {
LayoutDiv,
},
data() {
return {
email:'',
password:'',
validationErrors:{},
isSubmitting:false,
};
},
created() {
if(localStorage.getItem('token') != "" && localStorage.getItem('token') != null){
this.$router.push('/dashboard')
}
},
methods: {
loginAction(){
this.isSubmitting = true
let payload = {
email: this.email,
password: this.password,
}
axios.post('/api/login', payload)
.then(response => {
localStorage.setItem('token', response.data.token)
this.$router.push('/dashboard')
return response
})
.catch(error => {
this.isSubmitting = false
if (error.response.data.errors != undefined) {
this.validationErrors = error.response.data.errors
}
if (error.response.data.error != undefined) {
this.validationErrors = error.response.data.error
}
return error
});
}
},
};
</script>
src/components/pages/RegisterPage.vue
<template>
<layout-div>
<div class="row justify-content-md-center mt-5">
<div class="col-4">
<div class="card">
<div class="card-body">
<h5 class="card-title mb-4">Register</h5>
<form >
<div class="mb-3">
<label
htmlFor="name"
class="form-label">Name
</label>
<input
type="text"
class="form-control"
id="name"
name="name"
v-model="name"
/>
<div v-if="validationErrors.name" class="flex flex-col">
<small class="text-danger">
{{validationErrors?.name[0]}}
</small >
</div>
</div>
<div class="mb-3">
<label
htmlFor="email"
class="form-label">Email address
</label>
<input
type="email"
class="form-control"
id="email"
name="email"
v-model="email"
/>
<div v-if="validationErrors.email" class="flex flex-col">
<small class="text-danger">
{{validationErrors?.email[0]}}
</small >
</div>
</div>
<div class="mb-3">
<label
htmlFor="password"
class="form-label">Password
</label>
<input
type="password"
class="form-control"
id="password"
name="password"
v-model="password"
/>
<div v-if="validationErrors.password" class="flex flex-col">
<small class="text-danger">
{{validationErrors?.password[0]}}
</small >
</div>
</div>
<div class="mb-3">
<label
htmlFor="confirm_password"
class="form-label">Confirm Password
</label>
<input
type="password"
class="form-control"
id="confirm_password"
name="confirm_password"
v-model="confirmPassword"
/>
</div>
<div class="d-grid gap-2">
<button
:disabled="isSubmitting"
@click="registerAction()"
type="button"
class="btn btn-primary btn-block">Register Now
</button>
<p
class="text-center">Have already an account <router-link to="/">Login here</router-link>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
</layout-div>
</template>
<script>
import axios from 'axios';
import LayoutDiv from '../LayoutDiv.vue';
export default {
name: 'RegisterPage',
components: {
LayoutDiv,
},
data() {
return {
name:'',
email:'',
password:'',
confirmPassword:'',
validationErrors:{},
isSubmitting:false,
};
},
created() {
if(localStorage.getItem('token') != "" && localStorage.getItem('token') != null){
this.$router.push('/dashboard')
}
},
methods: {
registerAction(){
this.isSubmitting = true
let payload = {
name:this.name,
email: this.email,
password: this.password,
password_confirmation: this.confirmPassword
}
axios.post('/api/register', payload)
.then(response => {
localStorage.setItem('token', response.data.token)
this.$router.push('/dashboard')
return response
})
.catch(error => {
this.isSubmitting = false
if (error.response.data.errors != undefined) {
this.validationErrors = error.response.data.errors
}
return error
});
}
},
};
</script>
Step 5: Run the app
We’re all done, what is left is to run the app.
npm run serve
Open this URL:
http://localhost:8080/
Screenshots:
Login Page
Register Page
Dashboard Page