How to Upload Info Vue Login Signup
Look for the 🛠️️ emoji if you'd like to skim through the content while focusing on the build steps.
In this commodity, yous'll learn how to build a Vue website that will showcase events hosted by an organization. Users will sign in to view the details page of an event, and so you'll also add authentication to the website. You'll learn some Vue background, Vue awarding construction, creating components, setting upwardly routing, and styling with Bulma.
You can find the final lawmaking in this GitHub repository if you'd like to run across the end upshot now.
❗ If you already accept a Vue application and but want to add together hallmark, bound to this section to larn how.
⚡️ This is a two-part tutorial! Part one does not cover authorization. You will set the stage for part two by building the website and integrating user login. So in part two, you'll larn how to but show certain information if a user is signed in and has been authorized to admission that data.
Requirements
This application is using the latest versions (at the fourth dimension of writing — 8/8/2020) of the following:
- Vue.js (
2.half-dozen .11
) - Node.js (
12.18 .two
)
Note: This tutorial uses Vue 2. The release for Vue 3 is scheduled for the third quarter of 2020, only that doesn't mean you shouldn't outset with Vue two! This tutorial lays down the foundations of Vue that will carry over into the next release besides.
You tin can download Node.js hither, which automatically installs npm, a Node package managing director, as well.
Npm allows you to quickly install millions of libraries and hands manage any dependencies you take in your applications. You'll come across how beneficial this is presently.
This tutorial will walk you through how to create everything from scratch, then you don't need to have any prior knowledge of Vue or Node to follow along! You will, even so, need a lawmaking editor (VS Code is my favorite) and admission to the final to follow this tutorial.
Permit's become started!
Why Larn Vue?
Vue history and popularity
Vue.js is a JavaScript framework created by Evan You that has diddled upward in popularity over the last few years.
Source: 2018 State of JS Survey Involvement in Vue.js has nigh tripled from 2016 to 2018 with an increase in those who are interested in learning information technology and those who would use it again.
Source: 2018 Country of JS Survey In 2018, the majority of people surveyed have heard of Vue.js and would like to learn it or take already used it and would employ it again.
Evan You launched the projection after having worked on several AngularJS projects when he worked for Google. Vue isn't backed by huge companies like Google (Angular) or Facebook (React), merely as you tin see in the charts higher up, Vue is still able to stand up on its own amidst the top JavaScript frameworks.
Because of Evan Y'all's history at Google, you might even detect some similarities betwixt Vue and AngularJS (old Angular).
I figured, what if I could but extract the part that I really liked near Angular and build something really lightweight.
— Evan You on creating Vue.js
Vue vs. Angular vs. React
One of the best things about Vue is the low barrier to entry.
Source: 2018 State of JS Survey For developers who chose "would use again", their favorite Vue.js features were the easy learning curve, elegant programming manner, and good documentation.
A lot of other frameworks may require (or strongly suggest) that yous acquire their ain syntax or integrate other technologies (e.chiliad., TypeScript for Athwart or JSX for React). Of course, there's nothing wrong with this, but it does go far a picayune harder for a beginner to get started when they have to know all the things right away. Vue allows you lot to use TypeScript or even JSX if you'd like, but information technology's not required. This isn't to say one method is better than the other, but this HTML-like syntax is 1 possible caption equally to why developers find Vue easier to learn initially.
Once again, when information technology comes to comparing the popular frameworks, none of them are ameliorate than the others. At the end of the twenty-four hour period, it comes down to what you feel most comfortable using.
Vue is a keen selection if you're looking to get something up and running quickly. It has great community support, robust documentation in several languages, and it'due south just fun to utilise!
Setting Up
Alright, allow'south get started with some code.
First, open your terminal and switch to the directory that you want to shop the project in.
You're going to create this new project using the Vue CLI.
🛠️️ The Vue CLI tool helps get up and running with Vue quickly by letting yous choose from pre-configured build setups. To utilize the CLI, run the following in your terminal:
npx @vue/cli create events-app
This creates a new binder called events-app
and starts the installation procedure in that folder.
Annotation:
npx
allows you to utilize the Vue CLI without installing it globally. Information technology's available in versions of npm >= five.2.0.
The CLI volition at present ask you a few questions then that it can gear up the app correctly. The options that this tutorial uses are listed below. Press ENTER
to select.
🛠️️ Step 1: Pick a preset — Manually select features
? Please selection a preset: default (boom-boom, eslint) > Manually select features
🛠️️ Step 2: Check the features needed — Babel
, Router
, CSS Pre-processors
, Linter/Formatter
Press
Infinite
to select multiple features andENTER
once you lot have all features selected.
? Cheque the features needed for your projection: (Printing <infinite> to select, <a> to toggle all, <i> to invert pick) ◉ Babel ◯ TypeScript ◯ Progressive Web App (PWA) Support ◉ Router ◯ Vuex ◉ CSS Pre-processors ◉ Linter / Formatter ◯ Unit of measurement Testing ◯ E2E Testing
🛠️️ Stride 3: History way — Y
? Use history mode for router? (Requires proper server setup for alphabetize fallback in production) (Y/n) Y
Note: This will remove the default hash (#) from URLs.
🛠️️ Step four: CSS pre-processor — Sass/ SCSS ( with sprint-sass)
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Apply arrow keys) ❯ Sass/SCSS (with dart-sass) Sass/SCSS (with node-sass) Less Stylus
Annotation: Dart Sass is the primary implementation of Sass.
🛠️️ Pace 5: Option a linter/formatter —ESLint with error prevention only
? Pick a linter / formatter config: (Use pointer keys) ❯ ESLint with error prevention simply ESLint + Airbnb config ESLint + Standard config ESLint + Prettier
🛠️️ Step 6: Additional lint features — Lint and fix on commit
? Pick boosted lint features: ◯ Lint on save ❯ ◉ Lint and ready on commit
🛠️️ Step 7: Config location — In defended config files
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use pointer keys) ❯ In dedicated config files In package.json
🛠️️ Pace 8: Relieve equally preset — N
? Relieve this every bit a preset for future projects? (y/Due north) Northward
At present the CLI will configure your application. It will likewise install the dependencies, so give it a little fourth dimension (~30 seconds).
🛠️️ Once it's finished, y'all can showtime the application past running npm run serve
or yarn serve
:
cd events-app npm run serve
Run across it in activity at http: / / localhost:8080 /
! Get alee and go along this running in the background so that you tin can see the app's progress as you lot go through the tutorial.
"The Vue CLI helps you lot become up and running with Vue.js in seconds!"
Tweet This
Vue App Architecture
At present open your project in your code editor, and you'll see some default files that the CLI created. Allow'due south clean some of this upwardly.
🛠️️ Delete these files:
src/components/HelloWorld.vue
src/avails/logo.png
🛠️️ At present open up up src/views/Abode.vue
and replace it with the following:
<template > <div class = "home" > </div > </template > <script > export default { name: 'habitation' , components: { } , } ; </script >
This volition leave yous with a blank homepage and a nav bar with 2 links: Home and About.
Let's take a quick look at the important remaining files and so that you can run across how they piece of work together.
main.js
The first file to notation is the src/main.js
file. This will be the entry point for your Vue application.
import Vue from 'vue' ; import App from './App.vue' ; import router from './router' ; Vue.config.productionTip = imitation ; new Vue ( { router, return : ( h ) => h (App) , } ) . $mount ( '#app' ) ;
You take your imports at the top of the file:
- Vue itself
- The
App
component (which we'll become over in a moment) - The router (created past the CLI).
Next, you lot have Vue.config.productionTip = simulated
, which sets the app in development mode.
And finally, you're creating a new Vue instance at the bottom.
A Vue instance is required for every Vue application. The Vue instance will take an options
object that contains information almost your awarding, such as the DOM chemical element that the Vue example will exist mounted on, data the case volition use, functions that run at some point during the instance's lifecycle, and more.
In this case, the Vue example is using the router, rendering the app with the App
template (more on this soon), and then mounting it to the DOM element with the id
of app
.
index.html
Next, open upward public /index.html
, and you lot'll see a adequately standard index
HTML file.
<! DOCTYPE html > <html lang = "en" > <head > <meta charset = "utf-viii" /> <meta http-equiv = "X-UA-Compatible" content = "IE=border" /> <meta proper name = "viewport" content = "width=device-width,initial-scale=1.0" /> <link rel = "icon" href = "<%= BASE_URL %>favicon.ico" /> <title > <%= htmlWebpackPlugin.options.title %> </title > </head > <body > <noscript > <strong > Nosotros're sorry but <%= htmlWebpackPlugin.options.championship %> doesn't work properly without JavaScript enabled. Please enable it to continue. </potent > </noscript > <div id = "app" > </div > <!-- built files volition be auto injected --> </body > </html >
If you lot look toward the lesser of the file, you'll see where that mysterious #app
in the src/main.js
file comes into play. That div
is where the Vue instance volition be injected.
App.vue
The next of import file is src/App.vue
. This is your first component!
Y'all don't need to know all of the details of this file yet, but know that this is the adjacent "edifice block" of your Vue application. When you reviewed the src/master.js
file, you saw it was importing and rendering a template called App
, which is what this file is.
Before diving into the details of this file, let's first learn virtually what a component even is past reviewing Vue's component system.
Using Components in Vue
The concept of components, in general, is sometimes over-complicated, but in reality, it'due south quite simple. A component is a modular and reusable cake of code. Information technology contains all of the HTML, JavaScript, and CSS that it requires for its functionality.
Imagine you lot accept a simple website that has two pages: a home page and a portfolio folio.
- Home page — Contains some images, bones information, and a carousel with some testimonials
- Portfolio page — Contains some images and descriptions of your piece of work
You decide that y'all want your Portfolio folio to include all of the testimonials that are on your homepage as well.
In this scenario, you can copy/paste all of the code required for the testimonials onto both pages, but and then you'd be breaking the golden Dry out ("Don't Echo Yourself") rule.
This is where the idea of components starts to brand sense. Instead of creating duplicate code, you can pull that testimonial lawmaking out and package information technology into its ain file. This standalone chunk of code will contain the HTML, the styles, and whatever JS needed to brand the carousel work.
Now, whenever you want to insert that testimonial "component" somewhere, all you lot take to do is import that component!
Your application volition begin to take on a sort of tree structure. You'll have your "root" component, which in this case is src/App.vue
, and that component will import other components. All of these small chunks of lawmaking come together to build your application.
Source: Vuejs.org
Now that you lot have the idea of components downwards, permit's see what a Vue component looks like.
Vue components
There are a lot of means to structure components in Vue. Let's look at the most pop style: Single file components.
Unmarried file components package up the template, logic, and styles used past a component into one file with a .vue
extension. This method requires a build setup, which the CLI has already fix up for you. Let'due south take a look at an example component.
<template > <div class = "our-component" > <h1 > I'm a component! </h1 > <ChildComponent /> </div > </template > <script > import ChildComponent from '@/components/ChildComponent' ; export default { proper name: 'MyComponent' , components: { ChildComponent, } , } ; </script > <way lang = "scss" scoped > .our-component { text-align : middle; } </style >
The HTML is enclosed in a <template> < /template>
tag. Within, yous'll see <ChildComponent / >
. This is an case of how you can utilise another component within of this one.
Annotation: Y'all must ever have a parent
<div>
element that encloses the rest of the HTML subsequently the template tag.
Adjacent, there is a script
tag, which includes:
- An
import
statement that allows you to import and use other components inside this component. - An
consign
object that allows y'all to define and export this named component to reuse information technology across your application. - A
components
object inside the export where you tin can list all of the child components used in this component.
Annotation: This is a pretty basic example, just at that place are loads of other component options you lot tin can include in your component object.
Next, there is the <mode>
tag. The styles defined here apply to this component and all of its children. In this case, even so, at that place is a scoped
belongings added, which restricts these styles to only this component. And finally, you're also specifying that you're using SCSS equally the stylesheet language.
Let's take a look at that App.vue
file once more now that you have a little more than background most component structure.
App.vue
Open upwards src/App.vue
.
<template > <div id = "app" > <div id = "nav" > <router-link to = "/" > Home </router-link > | <router-link to = "/nearly" > About </router-link > </div > <router-view /> </div > </template > <manner lang = "scss" > #app { font-family : 'Avenir' , Helvetica, Arial, sans-serif; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing : grayscale; text-marshal : center; color : #2c3e50; } #nav { padding : 30px; a { font-weight : bold; color : #2c3e50; &.router-link-exact-active { color : #42b983; } } } </style >
This is the first view template to be rendered in your application. The rest of the components will start from here.
Take a await at <router-link>
and <router-view>
. This is how your application will handle routing. If you chose to have the router born using the CLI, you already have a nice template here to apply!
We'll go more in-depth on routing before long, but just know that when you click on one of those links, this same template will still be rendered, but <router-view / >
will be replaced with whatever route is agile. In this case, either the Home
or About
component. This is how you lot'll exist able to reuse this same layout and navbar beyond the entire application.
Try clicking those links to see for yourself!
Building Application Components
Now that y'all know the anatomy of a Vue application and how to build a component, it's time to kickoff edifice!
🛠️️ Brand certain y'all're still in the events-app
folder in the last and then create these files/folders:
cd src/views touch EventSingle.vue
Notation: If yous're on Windows, the
bear upon
command may not work, depending on your setup. You tin always create the file manually instead.
🛠️️ Now brand the components that will exist shared among these pages:
cd ../components touch EventsList.vue touch EventCard.vue mkdir partials affect partials/Nav.vue
That should exercise it for at present! Let's start filling these files in and go over the purpose of each file.
Using Bulma for Styling
To make styling a little easier, you lot're going to use Bulma, which is an open-source CSS framework.
🛠️️ Switch to the events-app
binder and then enter the control below to install Bulma:
cd ../.. npm install bulma
🛠️️ Now open up src/main.js
in your editor and import Bulma by calculation this to the top of the file afterwards all of the other imports:
// ... import 'bulma/css/bulma.css' ; // ...
🛠️️ Outset the app up one more time so that y'all tin can meet your work in progress equally yous continue edifice in the next section.
npm run serve
You lot can but leave this running in the background for the rest of this tutorial, and you'll always be able to view it in the browser at http: / /localhost: 8080
.
Domicile Component
Now let's start working on the components.
🛠️️ Open up the Abode Component in src/views/Home.vue
and paste in the following:
<template > <div form = "home" > <section class = "hero is-nighttime" > <div course = "hero-trunk" > <div class = "container" > <h1 class = "title" > Welcome to the Fauna Rescue League </h1 > <h2 course = "subtitle" > Make certain yous cheque out our upcoming events beneath </h2 > <div class = "button-block" > <button class = "button is-twoscore is-dark" > Sign Up to Browse Events </button > </div > </div > </div > </department > </div > </template > <script > export default { name: 'home' , components: { } , } ; </script > <style lang = "scss" scoped > .hero { text-marshal : center; background-paradigm : url ( 'https://cdn.auth0.com/weblog/vue-meetup/result-imprint.png' ) ; background-size : embrace; background-position : eye; background-echo : no-repeat; tiptop : 400px; } .hero-body .title { text-shadow : 4px 4px 4px rgba (0, 0, 0, 0.6) ; padding : 40px 0 20px 0; font-size : 60px; } .subtitle { text-shadow : 4px 4px 4px rgba (0, 0, 0, 0.7) ; font-size : 30px; } .button-block { text-align : center; margin-left : machine; margin-correct : auto; width : 100%; position : accented; bottom : -150px; .button { margin-right : 50px; padding-left : 50px; padding-right : 50px; } .welcome { width : 400px; padding : 10px; margin-left : auto; margin-correct : auto; } } .is-xl { font-size : i.7rem; } </style >
This will requite you lot a big banner and button at the summit of the page. The button will lead to the signup form, which you'll wire up later.
About Component
The Nigh
component comes default with the Vue install, just allow'due south just spruce it upward a picayune.
🛠️️ Open up up src/views/Almost.vue
, and supervene upon all of it with this:
<template > <div form = "well-nigh" > <div grade = "hero is-primary" > <div grade = "hero-trunk" > <div class = "container" > <h1 course = "championship is-size-1" > About Fauna Rescue League </h1 > </div > </div > </div > <div class = "container" > <p form = "org-description is-size-4" > Lorem ipsum dolor sit amet consectetur adipisicing elit. Eius quia aperiam eligendi dolorum reprehenderit ea amet, aliquid dolorem beatae, iste aliquam ullam. Sequi ab eligendi consectetur neque laudantium, libero asperiores. </p > <p class = "org-description is-size-iv" > Lorem ipsum dolor sit amet consectetur adipisicing elit. Eius quia aperiam eligendi dolorum reprehenderit ea amet, aliquid dolorem beatae, iste aliquam ullam. Sequi ab eligendi consectetur neque laudantium, libero asperiores. </p > </div > </div > </template > <mode lang = "scss" scoped > .org-description { margin-top : 50px; } </style >
Nav Component
🛠️️ At present fix up the nav. Open src/components/partials/Nav.vue
and paste this in:
<template > <nav class = "navbar container" role = "navigation" aria-label = "main navigation" > <div course = "navbar-brand" > <a form = "navbar-item" href = "/" > <strong form = "is-size-four" > Animal Rescue League </strong > </a > <a role = "push" class = "navbar-burger burger" aria-label = "carte du jour" aria-expanded = "fake" data-target = "navbarBasicExample" > <bridge aria-hidden = "true" > </span > <span aria-hidden = "true" > </span > <span aria-hidden = "truthful" > </span > </a > </div > <div id = "navbar" class = "navbar-menu" > <div course = "navbar-start" > <router-link to = "/" class = "navbar-particular" > Home </router-link > <router-link to = "/virtually" class = "navbar-particular" > About </router-link > </div > <div class = "navbar-end" > <div course = "navbar-item" > <div class = "buttons" > <a class = "push is-dark" > <strong > Sign In </strong > </a > </div > </div > </div > </div > </nav > </template > <script > export default { proper name: 'Nav' , } ; </script > <mode lang = "scss" scoped > nav { margin-top : 25px; margin-lesser : 30px; a { font-weight : bold; color : #2c3e50; &.router-link-exact-active { color : #d88d00; } } } </style >
If you lot refresh, y'all'll observe the nav doesn't change. That's considering you're not really using this component anywhere.
🛠️️ Open up src/App.vue
and supplant it with this:
<template > <div id = "app" > <nav /> <router-view /> </div > </template > <script > import Nav from './components/partials/Nav.vue' ; export default { name: 'app' , components: { Nav, } , } ; </script > <way lang = "scss" > #app { font-family : 'Avenir' , Helvetica, Arial, sans-serif; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing : grayscale; colour : #2c3e50; } </fashion >
Since yous're defining the router links in the Nav
component now, yous can get rid of them in this file. All you demand to practise is import the Nav
component. The old #nav
styles have as well been deleted since the Nav
component has its own styles.
At present, if you lot refresh, you should see your new nav! Yous can even click around, and information technology'll open up upwards the unlike routes you've specified in the Nav
component.
Adjacent upwardly, you'll add a component to your Home
page.
EventsList Component
🛠️️ Open up src/components/EventsList.vue
and paste this in:
<template > <div class = "events container" > <h2 class = "subtitle is-iii" > Bank check out our upcoming events </h2 > <div class = "columns is-multiline" > <div class = "column is-one-quarter" > <EventCard /> </div > </div > </div > </template > <script > import EventCard from '@/components/EventCard' ; consign default { name: 'EventsList' , components: { EventCard, } , } ; </script > <style lang = "scss" scoped > .events { margin-top : 100px; text-marshal : center; } </style >
This volition create a cake of cards that takes upwards 1/four of the row (by using Bulma's column
with is-1-quarter
). Each of those 1/4 slots will exist filled with the EventCard
component.
🛠️️ For now, simply echo that carte lawmaking a couple of times and so that you can see how the structure volition look.
<div class = "columns is-multiline" > <div class = "column is-one-quarter" > <EventCard /> </div > <div course = "column is-one-quarter" > <EventCard /> </div > </div >
Next you need to:
- Import this into the
Home
component - Add together information technology to the list of components that
Home
uses inexport default { }
- Slot information technology into the appropriate place in the
Dwelling
template
🛠️️ Open up src/views/Home.vue
and supercede the script
section with this:
<script > import EventsList from '../components/EventsList' ; export default { name: 'domicile' , components: { EventsList, } , } ; </script >
🛠️️ Now in the template department, call the component with <EventsList / >
.
<template > <div course = "home" > <section class = "hero is-dark" > <!-- ... --> </section > <EventsList /> </div > </template >
You should now see the subtitle text, "Check out our upcoming events", rendered below the homepage banner. However, none of the individual cards are showing all the same. That's because you haven't created them.
Event Menu Component
🛠️️ Open up src/components/EventCard.vue
and paste in:
<template > <div form = "event-card" > <div class = "carte du jour" > <div class = "card-content" > <h2 class = "is-size-4 has-text-weight-assuming" > Event name </h2 > <minor class = "effect-date" > Event date </modest > <span > Issue location </span > </div > </div > </div > </template > <script > export default { } ; </script > <style lang = "scss" scoped > .carte { background-prototype : url ( 'https://placekitten.com/400/400' ) ; meridian : 200px; background-position : middle; groundwork-size : cover; text-align : eye; } .card-content { padding-top : 50px; position : absolute; colour : #fff; groundwork-color : rgba (0, 0, 0, 0.35) ; top : 0; padding : 10px; pinnacle : 200px; width : 100%; span { font-size : 18px; text-align : center; width : 100%; position : absolute; bottom : 10px; right : 0; } h2 { margin-top : 10px; } } .outcome-date { background-color : #151515; colour : #fff; font-size : 0.75em; padding : 2px 10px; position : absolute; top : 0; right : 0; } </mode >
You lot should now run into the ii cards filled in with some mock content.
Of course, you're going to want each bill of fare to be unique and correspond an bodily event. You lot'll come back to this component presently to see how y'all can feed data in and accomplish this.
For now, finish setting up the rest of your components.
Event Single Component
🛠️️ Open up src/views/EventSingle.vue
and paste this in:
<template > <div form = "event-single" > <section class = "hero is-primary" > <div class = "hero-body" > <div class = "container" > <h1 course = "title" > Issue name </h1 > <h2 class = "subtitle " > Event date </h2 > </div > </div > </section > <section class = "event-content" > <div class = "container" > <p class = "is-size-4 description" > Event description </p > <p class = "is-size-four" > Location: </p > <p form = "is-size-4" > Category: </p > <div class = "outcome-images columns is-multiline has-text-centered" > <div grade = "column is-i-third" > Image PLACEHOLDER </div > </div > </div > </section > </div > </template > <script > consign default { } ; </script > <style lang = "scss" scoped > .result-single { margin-summit : 30px; } .hero { margin-bottom : 70px; } .event-images { margin-top : 50px; } .description { margin-bottom : 30px; } </fashion >
This will be the page that appears when a user clicks on an event from the list on the homepage. Considering this page doesn't actually exist even so, this is a bully time to revisit your router.
Router paths
🛠️️ Open upward src/router/index.js
and replace the contents with this:
import Vue from 'vue' ; import Router from 'vue-router' ; import Home from '../views/Home.vue' ; Vue. apply (Router) ; export default new Router ( { mode: 'history' , base: procedure.env. BASE_URL , routes: [ { path: '/' , name: 'domicile' , component: Habitation, } , { path: '/about' , name: 'about' , component : ( ) => import ( '../views/Nearly.vue' ) , } , { path: '/result/:id' , name: 'eventSingle' , component : ( ) => import ( '../views/EventSingle.vue' ) , } , ] , } ) ;
Press save and navigate to http: / /localhost: 8080 /event/ 1
. You should at present encounter the contents of the EventSingle
component!
If you look under path
in the router, you lot'll see a route parameter, :id
. This is how you'll create split pages for every event. Once yous add in the data, you can navigate to any event by appending its id
to the end of / event /
.
Let'south work on adding data now.
Calculation Data to your Vue App
To keep this tutorial focused on the basics of Vue, y'all're just going to create an array of objects (where each object is an effect) and store it in the component that needs it.
Ideally, you would want to pull information from an API to dynamically fill in the cake of cards, but that's a little outside the scope of this tutorial. If you're interested in making calls to an API using Vue and securing any data you have, make sure you lot read part ii of this tutorial where you'll do just that!
Allow's revisit those three components that were missing dynamic data and see how to fill them in.
EventsList Component
🛠️️ Head back to the EventsList
component in src/components/EventsList.vue
and roll down to the bottom where the <script>
tag starts. Supercede the entirety of <script> < /script>
with this:
<script > import EventCard from '@/components/EventCard' ; export default { proper name: 'EventsList' , components: { EventCard, } , data ( ) { return { event: { } , events: [ { id: 1 , name: 'Charity Brawl' , category: 'Fundraising' , clarification: 'Spend an elegant night of dinner and dancing with us every bit we raise money for our new rescue farm.' , featuredImage: 'https://placekitten.com/500/500' , images: [ 'https://placekitten.com/500/500' , 'https://placekitten.com/500/500' , 'https://placekitten.com/500/500' , ] , location: '1234 Fancy Ave' , date: '12-25-2019' , fourth dimension: '11:30' , } , { id: 2 , proper name: 'Rescue Center Goods Drive' , category: 'Adoptions' , description: 'Come to our donation bulldoze to help us replenish our stock of pet food, toys, bedding, etc. Nosotros will have live bands, games, nutrient trucks, and much more.' , featuredImage: 'https://placekitten.com/500/500' , images: [ 'https://placekitten.com/500/500' ] , location: '1234 Dog Aisle' , date: '11-21-2019' , fourth dimension: '12:00' , } , ] , } ; } , } ; </script >
The but thing that'due south changing here is the addition of a data ( )
function that returns an empty object chosen upshot
and an array called events
.
- The
events
array holds 2 objects that each correspond to a different outcome - The
result
object will hold a single event to be passed to the child component,EventCard
Next, you lot need to change the HTML portion of this file to loop through these events and so send each one down the chain to be rendered by the kid component, EventCard
.
🛠️️ Supplant everything between the <template> < /template>
tags with:
<template > <div course = "events container" > <h2 course = "subtitle is-3" > Check out our upcoming events </h2 > <div form = "columns is-multiline" > <div five-for = "consequence in events" :consequence = "upshot" :cardinal = "event.id" form = "column is-one-quarter" > <router-link :to = " '/event/' + event.id" > <EventCard :event = "event" /> </router-link > </div > </div > </div > </template >
Allow's take a closer look at the block of code that changed (spaced out for better readability).
<div v-for = "outcome in events" :upshot = "result" :key = "event.id" class = "cavalcade is-ane-quarter" > <router-link :to = " '/event/' + issue.id" > <EventCard :issue = "consequence" /> </router-link > </div >
You tin can loop over the events in the events
array using the Vue directive v- for
. This acts equally a for
loop and pulls out each issue individually then that it tin exist rendered separately past the EventCard
component.
This is also the first time you're seeing a directive!
A directive is a special type of markup that you can utilise to do something to a DOM element. In Vue, these all begin with v-
. Then, in this case, you're using the shorthand 5- for
to create a for
loop. Another common instance is v- if
, which creates a conditional inside the template. You tin can run across a total listing of Vue directives here.
Here, you're using Vue'south :key
aspect to bind a unique key (in this instance, id
) to each upshot.
Annotation: In Vue,
:
is shorthand for5-bind
.
Y'all're besides binding the value of the electric current event
in the for
loop to the event
object you created earlier with :outcome= "issue"
. This volition allow y'all to transport this object downwards to the child component to be rendered separately.
Next, you're using <router-link>
to make each card into a clickable link. Back in the router.js
file, you created the road / outcome / :id
with a route parameter of id
. This route uses the EventSingle
component, which will render the page for each specific effect. You're using the id
from each event to make sure it links to the right outcome page.
Go alee and click one, and yous'll run into that it links to the single result page that you lot created.
Finally, you're calling the EventCard
component to fill in each individual card. You're sending a variable chosen outcome
downwardly to the card and then passing in the current outcome
from the for
loop.
Right now, the EventCard
component isn't prepared to accept information, then let's prepare that.
EventCard Component
🛠️️ Open the EventCard
component in src/components/EventCard.vue
. Curl down to where you have the <script> < /script>
tags and replace information technology with this:
<script > consign default { props: [ 'event' ] , } ; </script >
This component has something new: props
.
Whenever your component is expecting information, y'all should add that data'due south variable name to the props
choice. props
is kind of a funny give-and-take, only it actually but ways property.
A prop is a property on a component.
This is where you define the information that the component should be expecting from its parent component.
This event
prop was passed to the current component from the parent component. This allows you to brandish it in the HTML template using curly braces:
{{ event }}
This is known as interpolation. Using string interpolation, yous're able to display the value of consequence
in your template. This is a course of data-bounden, which ways that whenever the value of result
in data
changes, the displayed value in the template will also change.
🛠️️ To come across this in action, go alee and update the template section of EventCard.vue
with this:
<template > <div form = "result-card" > <div class = "card" > <div class = "carte-content" > <h2 class = "is-size-iv has-text-weight-bold" > {{ event.name }} </h2 > <modest class = "event-date" > {{ outcome.date }} </small-scale > <bridge > {{ event.location }} </span > </div > </div > </div > </template >
If yous become back to the homepage in your browser, you'll see the cards at present accept the correct data!
Just to summarize, the parent component, EventsList
, sent the event information downwards from the for
loop two separate times. Each fourth dimension the EventCard
component was called, it received the event
data into props
, which immune you to render the name, date, and location.
EventSingle Component
The last office of the application that needs updated data is the EventSingle
component. Open up up src/views/EventSingle.vue
.
You can run across the current state of this component in the browser at http: / /localhost: 8080 /event/ one
. Everything is still difficult-coded in and waiting for data.
This component is a great example of how passing data starts to get tricky.
Think back to how the link to this page was gear up in EventsList.vue
:
<router-link :to = " '/event/' + event.id" > <EventCard :event = "event" /> </router-link >
It uses the event.id
from the for
loop to create the link for each card/event, but how exercise y'all send the actual data through?
You can employ a method similar to the one you lot used earlier to make full in the data from EventCard
and send some data down into a prop
on EventSingle
. Simply then you'd be using the router to manage data, which is a little foreign.
You lot also accept to consider what would happen if instead of clicking on the link, someone went directly to http: / /localhost: 8080 /outcome/ ane
. How would information technology receive the props that it's expecting if that specific <router-link>
code was never fired?
It wouldn't.
So for this application, your best selection is to just pull the information again.
Here's the gist of what needs to happen:
- Take hold of the
id
from the route parameter (in the URL) - Utilise that to pull out the correct upshot from the list of all events
- Make full in the template with data from that specific event
🛠️️ To exercise this, open up EventSingle.vue
and replace it entirely with:
<template > <div class = "issue-single" > <department class = "hero is-chief" > <div class = "hero-body" > <div grade = "container" > <h1 class = "title" > {{ event.name }} </h1 > <h2 class = "subtitle " > <potent > Date: </strong > {{ issue.engagement }} <br /> <strong > Time: </stiff > {{ event.fourth dimension }} </h2 > </div > </div > </section > <department course = "event-content" > <div class = "container" > <p class = "is-size-4 clarification" > {{ event.description }} </p > <p class = "is-size-5" > <potent > Location: </stiff > {{ event.location }} </p > <p class = "is-size-5" > <strong > Category: </strong > {{ consequence.category }} </p > <div class = "event-images columns is-multiline has-text-centered" > <div v-for = "image in consequence.images" :key = "paradigm.id" class = "column is-one-tertiary" > <img :src = "image" :alt = "outcome.proper name" /> </div > </div > </div > </section > </div > </template > <script > export default { name: 'EventSingle' , information ( ) { return { events: [ { id: one , proper name: 'Clemency Ball' , category: 'Fundraising' , description: 'Spend an elegant night of dinner and dancing with us as nosotros raise coin for our new rescue farm.' , featuredImage: 'https://placekitten.com/500/500' , images: [ 'https://placekitten.com/500/500' , 'https://placekitten.com/500/500' , 'https://placekitten.com/500/500' , ] , location: '1234 Fancy Ave' , date: '12-25-2019' , fourth dimension: 'eleven:30' , } , { id: ii , proper name: 'Rescue Heart Appurtenances Bulldoze' , category: 'Adoptions' , description: 'Come up to our donation drive to assistance united states of america furnish our stock of pet food, toys, bedding, etc. We will have live bands, games, nutrient trucks, and much more.' , featuredImage: 'https://placekitten.com/500/500' , images: [ 'https://placekitten.com/500/500' ] , location: '1234 Dog Alley' , engagement: '11-21-2019' , time: '12:00' , } , ] , consequence: { } , } ; } , created ( ) { const ID = Number ( this .$route.params.id) ; allow event = this .events. discover ( ( event ) => event.id === ID ) ; this .event = issue; } , } ; </script >
Scroll down to the <script>
section and you'll run across that the data you've been using has too been added to this component. But this fourth dimension, at that place's a new chunk of code:
created ( ) { const ID = Number ( this .$route.params.id) ; const event = this .events. find ( event => upshot.id === ID ) ; this .event = event; }
First, permit'south go over what created ( )
is used for.
The Vue case goes through many steps when it'south created. Information technology sets up information ascertainment, compiles the template, mounts the Vue instance to the DOM, and updates the DOM when changes are detected.
But what if you need to spring in at some point betwixt these steps and run some lawmaking? Vue offers functions chosen lifecycle hooks that let you lot do just that.
The created ( )
claw lets you run some code right after the instance is created.
There are quite a few lifecycle hooks available, as you tin see in the image beneath.
Image Source: Vue.js Guide - Example
Then right afterward the instance is created, the created ( )
function runs.
created ( ) { const ID = Number ( this .$route.params.id) ; const upshot = this .events. find ( effect => event.id === ID ) ; this .effect = event; }
This function creates a variable called ID
that will hold the id
of the event yous want to render. You're able to pull this id
from the road parameter id
that yous fix earlier in src/router/alphabetize.js
.
Next, yous're creating a variable called event
, which will concur the outcome object. It uses the JavaScript function discover ( )
on the events
array, which will loop through the assortment until it finds an upshot with the id
of ID
(the road parameter).
And so you lot're setting the consequence
variable to the result of this. And at present, you have the data needed to render this specific event!
Ideally, you'd want to pull this data from an API. In a case like this, you would merely hit the endpoint that returns the specific outcome that you want by sending over the route parameter, just since you don't have an API yet, this method is fine. In the follow up of this tutorial, y'all'll refactor this code to use an bodily API.
Another absurd affair you're doing is looping over the images in the specific consequence. Let's accept a closer await at the block of code that displays the images.
<div class = "result-images columns is-multiline has-text-centered" > <div v-for = "paradigm in event.images" :key = "image.id" class = "column is-1-third" > <img :src = "`${image}`" :alt = "`${outcome.name}`" /> </div > </div >
This uses Vue's v- for
directive once again to loop through the images. Once it grabs a unmarried image, it binds the image URL, img
, to the :src
aspect. It's good practice to always set an alt
aspect, and then you can bind the value for event.proper name
to the alt
attribute of these images.
At present head back to the homepage and click around. All of the components are rendering the right information, so it's time to add together authentication!
Adding Hallmark to your Vue App
The concluding thing left to do is add login functionality to the application. Yous're going to use Auth0's hallmark service to do this.
Once you're registered, you'll be taken to the Auth0 management dashboard.
- Click on "Applications" in the left sidebar
- Click on the big cherry push that says "Create Application"
- Name it "Vue Events" (or anything yous'd like)
- Click on "Single Folio Web Applications" for "application type"
- Click "Create"
🛠️️ Next, click into "Settings" to fill up in some information that Auth0 needs to configure authentication for your awarding.
Allowed Callback URLs — http: / /localhost: 8080
This is where Auth0 volition redirect the user after they take authenticated.
Allowed Logout URLs — http: / /localhost: 8080
This is the URL that users will return to after they log out of your application.
Immune Spider web Origins — http: / /localhost: 8080
This is the URL that Auth0 uses for Cross-origin Authentication.
Scroll downwards and click the "Save Changes" push.
That'southward all you need from the dashboard for now, but don't click out yet. Y'all'll need to pull some of these values from the dashboard into your application soon.
Install Auth0 SPA package
🛠️️ Head dorsum to the last and install Auth0's auth0-spa-js
package in the application'south root directory.
npm install @auth0/auth0-spa-js
Create an authentication wrapper
Next, you're going to create a reusable wrapper Vue object around the Auth0 SDK. You'll too create a Vue plugin that exposes this wrapper to the remainder of the application.
🛠️️ Create a new file and folder for this. Make sure you're still in the events-app
root directory and enter:
mkdir src/auth bear on src/auth/index.js
🛠️️ Now open up up the newly created src/auth/alphabetize.js
file and paste in the following:
import Vue from 'vue' ; import createAuth0Client from '@auth0/auth0-spa-js' ; /** Define a default action to perform after authentication */ const DEFAULT_REDIRECT_CALLBACK = ( ) => window.history. replaceState ( { } , document.championship, window.location.pathname) ; let instance; /** Returns the current example of the SDK */ export const getInstance = ( ) => instance; /** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */ export const useAuth0 = ( { onRedirectCallback = DEFAULT_REDIRECT_CALLBACK , redirectUri = window.location.origin, ...options } ) => { if (instance) return instance; // The 'case' is but a Vue object instance = new Vue ( { data ( ) { render { loading: true , isAuthenticated: simulated , user: { } , auth0Client: nix , popupOpen: false , error: null , } ; } , methods: { /** Authenticates the user using a popup window */ async loginWithPopup ( o ) { this .popupOpen = true ; try { wait this .auth0Client. loginWithPopup (o) ; } catch (east) { // eslint-disable-next-line panel. error (eastward) ; } finally { this .popupOpen = false ; } this .user = await this .auth0Client. getUser ( ) ; this .isAuthenticated = true ; } , /** Handles the callback when logging in using a redirect */ async handleRedirectCallback ( ) { this .loading = true ; try { expect this .auth0Client. handleRedirectCallback ( ) ; this .user = await this .auth0Client. getUser ( ) ; this .isAuthenticated = true ; } catch (e) { this .error = e; } finally { this .loading = false ; } } , /** Authenticates the user using the redirect method */ loginWithRedirect ( o ) { render this .auth0Client. loginWithRedirect (o) ; } , /** Returns all the claims present in the ID token */ getIdTokenClaims ( o ) { return this .auth0Client. getIdTokenClaims (o) ; } , /** Returns the access token. If the token is invalid or missing, a new one is retrieved */ getTokenSilently ( o ) { return this .auth0Client. getTokenSilently (o) ; } , /** Gets the admission token using a popup window */ getTokenWithPopup ( o ) { return this .auth0Client. getTokenWithPopup (o) ; } , /** Logs the user out and removes their session on the authorization server */ logout ( o ) { return this .auth0Client. logout (o) ; } , } , /** Utilize this lifecycle method to instantiate the SDK client */ async created ( ) { // Create a new instance of the SDK client using members of the given options object this .auth0Client = await createAuth0Client ( { domain: options.domain, client_id: options.clientId, audience: options.audience, redirect_uri: redirectUri, } ) ; try { // If the user is returning to the app after authentication.. if ( window.location.search. includes ( 'code=' ) && window.location.search. includes ( 'state=' ) ) { // handle the redirect and retrieve tokens const { appState } = expect this .auth0Client. handleRedirectCallback ( ) ; // Notify subscribers that the redirect callback has happened, passing the appState // (useful for retrieving any pre-hallmark state) onRedirectCallback (appState) ; } } catch (eastward) { this .error = east; } finally { // Initialize the internal authentication state this .isAuthenticated = await this .auth0Client. isAuthenticated ( ) ; this .user = await this .auth0Client. getUser ( ) ; this .loading = false ; } } , } ) ; return instance; } ; // Create a unproblematic Vue plugin to expose the wrapper object throughout the application export const Auth0Plugin = { install ( Vue, options ) { Vue .prototype.$auth = useAuth0 (options) ; } , } ;
The comments in this file cover the details of what's happening, but to summarize, you are kickoff creating (or returning) an instance of the Auth0 SDK. The instance is just a Vue object.
- The instance contains the following data:
loading
,isAuthenticated
,user
,auth0Client
,popupOpen
, anderror
- It also includes several methods that volition be chosen afterwards, but take note of them now:
loginWithPopup
,handleRedirectCallback
,loginWithRedirect
,getIdTokenClaims
,getTokenSilently
,getTokenWithPopup
, andlogout
During the created ( )
lifecycle hook, y'all're creating an case of the SDK.
When a user clicks "Log in", they're redirected to the Auth0 Universal Login page (more than on this later). They will enter their credentials there and and then be redirected back to the application. This is where the "Allowed Callback URLs" from the Auth0 dashboard come into play. handleRedirectCallback ( )
will run, which will get the authenticated user data, retrieve tokens, and update isAuthenticated
to true.
This instance too contains an options
object (pulled out and pasted below). This object will hold the values for the Auth0 clientId
, domain
, and audience
from the Auth0 dashboard.
// Create a new case of the SDK client using members of the given options object this .auth0Client = await createAuth0Client ( { domain: options.domain, client_id: options.clientId, audience: options.audition, redirect_uri: redirectUri, } ) ;
These values aren't particularly sensitive, but it'southward nonetheless a good practice to get out them out of your source control (due east.g. GitHub). Then permit'southward create a file that tin be added to .gitignore
so that Git will ignore it.
🛠️️ Make certain yous're still in the events-app
directory and run:
touch auth_config.json
If you're using Git or another version control, open up up .gitignore
or its equivalent. Paste in auth_config.json
on any line. Now this file will exist ignored the next fourth dimension yous push to your repo.
🛠️️ Next, open auth_config.json
and paste in the following:
{ "domain" : "your-domain.auth0.com" , "clientId" : "yourclientid" }
Finding your auth_config
values:
- Head to the Auth0 dashboard
- Click on "Applications" and select your application
- Click on "Settings"
- Copy the value for "Domain" and paste it into
domain
inauth_config.json
- Copy the value for "Client ID" and paste it into
clientId
inauth_config.json
Next, open src/primary.js
and install the plugin with Vue.use
. This plugin will let you to access the authentication state globally (from anywhere in the application). Vue.utilise
is a global method used to call plugins, and it must be placed before new Vue ( )
.
🛠️️ Replace all of src/chief.js
with the following:
import Vue from 'vue' ; import App from './App.vue' ; import router from './router' ; import 'bulma/css/bulma.css' ; // Import the Auth0 configuration import { domain, clientId } from '../auth_config.json' ; // Import the plugin here import { Auth0Plugin } from './auth' ; // Install the authentication plugin hither Vue. use (Auth0Plugin, { domain, clientId, onRedirectCallback : ( appState ) => { router. push ( appState && appState.targetUrl ? appState.targetUrl : window.location.pathname, ) ; } , } ) ; Vue.config.productionTip = false ; new Vue ( { router, render : ( h ) => h (App) , } ) . $mountain ( '#app' ) ;
Here you lot're but importing the Auth0 configuration file that you created to become access to the domain
and clientId
values. Adjacent, you're importing the Auth0Plugin
that was created before.
Finally, you install and configure the plugin.
Wiring up login and logout buttons
Now that you take the Auth0 authentication plugin configured, it'southward time to fix up the "Sign in" button so that it really does something.
🛠️️ Open up up src/components/partials/Nav.vue
. Find the block of code that starts with <div grade = "navbar-finish" >
and replace it with this:
<div class = "navbar-end" > <div course = "navbar-detail" > <div class = "buttons" > <!-- Check that the SDK client is not currently loading before accessing is methods --> <div v-if = "!$auth.loading" > <!-- show login when non authenticated --> <a v-if = "!$auth.isAuthenticated" @click = "login" class = "push is-nighttime" > <strong > Sign in </strong > </a > <!-- show logout when authenticated --> <a v-if = "$auth.isAuthenticated" @click = "logout" class = "button is-nighttime" > <stiff > Log out </strong > </a > </div > </div > </div > </div >
The buttons are now wrapped in !$auth.loading
to make sure that the SDK customer has finished loading earlier yous to try access the user's state. Next, you're using @click
, which will handle the click effect by calling the login
or logout
methods when a user clicks on the respective push button.
🛠️️ Allow's create those methods at present. In that aforementioned file, coil down to the <script>
tag and replace information technology with this:
<script> export default { name: 'Nav' , methods: { // Log the user in login ( ) { this .$auth. loginWithRedirect ( ) ; } , // Log the user out logout ( ) { this .$auth. logout ( { returnTo: window.location.origin } ) ; } } } < /script>
Now head back to the application and click "Sign In" and yous should exist redirected to the Auth0 Universal Login folio.
If y'all run into an effect, double-check that your values in
auth_config.json
are right. If y'all're even so having issues, go out a comment below, and I'll assist you work through it.
Once you've hit the Auth0 Universal Login page, sign up with a mock user business relationship. You'll and then see a screen telling you that the application is requesting access to your profile and email.
Click the checkmark, and you'll be redirected back to the "Allowed Callback URL" you specified in the dashboard, which is your application homepage. At present instead of the "Sign in" button, you should encounter a "Log out" button.
Optional: Auth0 offers social login options straight from the dashboard! Google is activated by default, and yous tin plough more than on individually in the Auth0 management dashboard.
Click on "Connections" > "Social" in the sidebar. Be certain to use your own dev keys if you'd like to integrate social sign-on. The default Auth0 dev keys are fine for testing, but may cause unexpected errors (such every bit beingness signed out on refresh), so we still recommend using your ain.
Accessing user information
Auth0 lets you access the information of the logged-in user in your templates with the post-obit:
{ { $auth.user; } }
The contents of $auth.user
look something like this:
{ "nickname" : "hollylloyd" , "proper name" : "Holly Lloyd" , "motion picture" : "https://gravatar.com/somefancyimage.png" , "updated_at" : "2019-10-09T15:49:28.181Z" , "email" : "holly-lloyd@example.com" , "email_verified" : imitation , "sub" : "auth0|xxxxxxxxxxxxxxx" }
So if you want to add a profile folio in the time to come, yous accept access to this data (and more) to display.
Now that you know how to add a login button, let'south wire up that second button on the homepage.
🛠️️ Open up src/views/Home.vue
and replace everything between <div class = "button-cake" > < /div>
with the following:
<div form = "button-block" > <button v- if = "!$auth.isAuthenticated" @click= "login" class = "button is-xl is-night" >Sign Upward to Browse Events< /button> <h3 5- if = "$auth.isAuthenticated" class = "is-size-3 has-background-night welcome" >Welcome, { { $auth.user.proper name } } ! < /h3> < /div>
🛠️️ Now you but need to add the methods section with the login ( )
function. Scroll downward to where the <script>
tag is and supersede export default { }
with this:
export default { name: 'home' , components: { EventsList, } , methods: { // Log the user in login ( ) { this .$auth. loginWithRedirect ( ) ; } , } , } ;
Now a user can sign in with this push button as well, and in one case they're signed in, it will be replaced with a welcome message with their name using $auth.user.proper name
.
Gear up a Road Guard
So now, the final thing you need to practise is redirect unauthenticated users abroad from the Single Consequence folio. This means they should be able to view the homepage with the list of cards/events, but every bit soon equally they click through to the event detail folio, they should exist kicked to a login folio.
⚡️ Of import ⚡️ This only prevents the page from loading; it doesn't preclude the data from loading. You lot should NEVER rely on the frontend to protect your data.
Since yous haven't created a backend API yet, yous're just storing all of the data in the component on the frontend. Fifty-fifty though you're going to prepare a route baby-sit to redirect an unauthenticated user away from a unmarried event page, they tin can still read through the JavaScript files and observe it! I'll show you how in a moment.
{% if page.url contains '/amp/' %} In part 2, you'll build out the API and so that this data is stored and protected on the backend instead and only pulled into the frontend if the user is authenticated. {% else %} In office 2, you'll build out the API then that this data is stored and protected on the backend instead and only pulled into the frontend if the user is authenticated. {% endif %}
Permit'due south set up the route guard now so that when the data is coming from the backend, the UI for kicking the user to the login folio is already in identify.
🛠️️ Create a file called authGuard.js
in the src/auth
directory.
{% prism bash %} touch src/auth/authGuard.js {% endprism %}
🛠️️ Open that upwardly in your editor and paste in the following:
import { getInstance } from './index' ; export const authGuard = ( to, from , next ) => { const authService = getInstance ( ) ; const fn = ( ) => { // If the user is authenticated, continue with the road if (authService.isAuthenticated) { return next ( ) ; } // Otherwise, log in authService. loginWithRedirect ( { appState: { targetUrl: to.fullPath } } ) ; } ; // If loading has already finished, check the auth land using `fn()` if ( !authService.loading) { return fn ( ) ; } // Sentry for the loading property to modify earlier checking isAuthenticated authService. $watch ( 'loading' , ( loading ) => { if (loading === faux ) { render fn ( ) ; } } ) ; } ;
This uses the getInstance
method from the src/auth/index.js
file, which will implement the part that prevents a route from being accessed if a user is not logged in.
If the user is authenticated, side by side ( )
is returned, which allows the user to go along to the clicked route. If the user isn't authenticated, they're redirected to the Auth0 Universal Login page.
Next, yous need to add this auth guard to the router and then that this runs earlier whatever view is returned.
You'll only cheque if the user is authenticated. If they are, let them through, if not, send them to the login page.
🛠️️ Open upward the router file in src/router/alphabetize.js
and add together supervene upon it with:
import Vue from 'vue' ; import Router from 'vue-router' ; import Dwelling from '../views/Home.vue' ; import { authGuard } from '../auth/authGuard' ; Vue. use (Router) ; consign default new Router ( { mode: 'history' , base: process.env. BASE_URL , routes: [ { path: '/' , proper name: 'domicile' , component: Home, } , { path: '/about' , name: 'about' , component : ( ) => import ( '../views/Virtually.vue' ) , } , { path: '/event/:id' , proper noun: 'eventSingle' , component : ( ) => import ( '../views/EventSingle.vue' ) , beforeEnter: authGuard, } , ] , } ) ;
The authGuard
is imported at the top. Since you only want to require hallmark for the issue details route, beforeEnter: authGuard
has been added to that road.
Now, if yous've already logged in previously, y'all can click on one of those event cards and you should yet be able to see the consequence unmarried folio.
Simply if you open an incognito window and try to access that same route, you'll be kicked to the login page, which is exactly what's expected!
Equally discussed before, this doesn't prevent a user from finding the data for that page.
If you're curious how this is possible, sign out or open up an incognito window, and so go to http: / /localhost: 8080 /js/app.js
in your browser. Now search for one of the event descriptions similar "Spend an elegant night of dinner and dancing with us every bit nosotros raise money for our new rescue farm.", and certain enough, there is the data!
So at this point, yous may be request, "Holly, then what is the point of the redirect?"
I'grand glad you asked! This is mostly meant for user experience! Imagine that the data is protected on the backend. You're going to want to signal that a user should be signed in to view that specific page. If you lot simply merely don't render any data on that page, the user will be faced with an empty page and recollect something is cleaved. In this scenario, redirecting them to the sign-in folio will easily signal that they demand to log in to view it!
In part two of this tutorial, you'll learn how to create an API in Express and pull the data into your Vue application from in that location. It uses the same Vue application that you just built, so if you lot're interested, you can hit the basis running!
Wrap Up
If this was your first fourth dimension working with Vue.js, hopefully this helped you empathise how everything comes together in a small-scale awarding. Just to recap, here are some of the topics that were covered in this tutorial:
- Using the Vue CLI
- Creating reusable components
- Setting up routing with Vue Router
- Styling with Bulma
- Using props and data
- Adding authentication to a Vue.js app
- Protecting routes with Vue navigation guards
Check out the side by side tutorial on this topic where you can have this existing Vue application, connect information technology to an Express API, and learn how to secure those API endpoints to protect the data. Thanks for reading!
Source: https://auth0.com/blog/beginner-vuejs-tutorial-with-user-login/
0 Response to "How to Upload Info Vue Login Signup"
Post a Comment