One place for hosting & domains

      Sort and Filter a Table Using Angular

      Introduction

      When building Angular applications, one of the cornerstones we will use is ng-repeat. Showing data is something that we do in applications like when we show a table of users or whatever other data we need to show our users. Today we’ll be looking at a way to sort and filter our tabular data. This is a common feature that is always useful so let’s look at what we’ll be building and dive right into the code.

      Here’s a quick demo: http://codepen.io/sevilayha/pen/AmFLE/

      Our application will allow us to:

      • Show a table of data (ng-repeat)
      • Sort by ascending or descending columns (orderBy)
      • Filter by using a search field (filter)

      These are three common functions in any application and Angular lets us implement these features in a very simple way. Let’s set up our sample application’s HTML and Angular parts and then look at how we can sort and filter.

      We’ll be using Bootstrap and Font Awesome to style our app. Let’s take a look at the Angular module first. This will be a simple module with one controller where we define a few variables and the list of data we’ll show to our users (we’ll be using sushi, yum). The files we will need are:

      Our demo is built inside of CodePen, so you can create the two files above or just work within your own CodePen. Here is the code for app.js

      
      angular.module('sortApp', [])
        .controller('mainController', function($scope) {
          $scope.sortType     = 'name'; 
          $scope.sortReverse  = false;  
          $scope.searchFish   = '';     
      
          
          $scope.sushi = [
            { name: 'Cali Roll', fish: 'Crab', tastiness: 2 },
            { name: 'Philly', fish: 'Tuna', tastiness: 4 },
            { name: 'Tiger', fish: 'Eel', tastiness: 7 },
            { name: 'Rainbow', fish: 'Variety', tastiness: 6 }
          ];
        });
      

      We have set the 3 variables and the list of sushi. Now let’s use this module in our HTML. Here is the HTML we’ll need for index.html:

      <div class="container" ng-app="sortApp" ng-controller="mainController">
        <div class="alert alert-info">
          <p>Sort Type: {{ sortType }}</p>
          <p>Sort Reverse: {{ sortReverse }}</p>
          <p>Search Query: {{ searchFish }}</p>
        </div>
      
        <table class="table table-bordered table-striped">
          <thead>
            <tr>
              <td>
                  Sushi Roll
                </a>
              </td>
              <td>
                Fish Type
                </a>
              </td>
              <td>
                Taste Level
                </a>
              </td>
            </tr>
          </thead>
          <tbody>
            <tr ng-repeat="roll in sushi">
              <td>{{ roll.name }}</td>
              <td>{{ roll.fish }}</td>
              <td>{{ roll.tastiness }}</td>
            </tr>
          </tbody>
        </table>
      </div>
      

      We are loading Bootstrap, Font Awesome, and Angular. We will also apply the Angular module named sortApp and the Angular controller called mainController to the tag.

      We are also using an ngRepeat to loop over the sushi in our $scope.sushi array we created in our Angular module.

      Great. We have the list of data displayed all nicely for our users. Now let’s offer them some functionality by letting them sort the table.

      We will be accomplishing this sorting feature using two of the variables that we created earlier ($scope.sortType and $scope.sortReverse). We will also be using the Angular orderBy filter. Basically, applying a combination of sortType and sortReverse variables to an orderBy clause in our ng-repeat will sort the table.

      <tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse">
      

      That’s all we need to change the sort order of our ngRepeat. If you refresh your page, you’ll see that your list is sorted by name in normal order. Now go into your Angular module and change the sortType variable to $scope.sortType="fish" and refresh the page. You’ll now see the table sorted by Fish Type. The next step is to change the headings of our table so that they will change the sortType variable. That will automatically sort our table without refreshing the page (as is the Angular way).

      Making Table Headings Clickable

      We’ll be adding links to our table headings. Let’s look at the thead section of our site and use ng-click to adjust the sortType variable.

      <td>
        <a href="#" ng-click="sortType = 'name';">
          Sushi Roll
        </a>
      </td>
      

      Now as you click the links across your table headers, you’ll see your table sorted since we are setting the sortType variable using ng-click.

      Changing the Sort Order

      Next up, we’ll be adding a way to change the sort order so users can sort by ascending or descending. The orderBy filter arguments offer a third parameter for reverse. We just have to pass in true or false to change the sort order. Currently, we have it set to false since we defined that as one of the variables earlier ($scope.sortReverse). The way we will give users the option to reverse the sort is to add sortReverse = !sortReverse in the ng-click of our table headers. This will change the order if users click the link.

      <td>
        <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
          Sushi Roll
        </a>
      </td>
      

      Just add that to all the other ng-clicks in the code as well. Now if you click your header links, you’ll see the sort order changing. This isn’t very intuitive right now though since we don’t provide any sort of visual feedback that the sort is changing. Let’s add carets to show up and down to represent our current sort order. We’ll add an up and down caret here and then use ngShow and ngHide to show and hide the caret based on order.

      <td>
        <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
          Sushi Roll
          <span ng-show="sortType == 'name' && !sortReverse" class="fa fa-caret-down"></span>
          <span ng-show="sortType == 'name' && sortReverse" class="fa fa-caret-up"></span>
        </a>
      </td>
      

      Now the up arrow will only show if sortType is name and sortReverse is set to true. Applying this to the other headers will give you the same effect. With a few Angular directives, we are now able to show proper feedback for sorting and for sort order. The last part of this tutorial will deal with filtering the table of data.

      Filtering data in an ng-repeat is fairly easy since Angular also comes with the filter module. There are only two things we need to do here: create the form and apply the form variable to the ng-repeat.

      Let’s create the form first. Above the code for the table and below the code for the alert.

      <form>
        <div class="form-group">
          <div class="input-group">
            <div class="input-group-addon"><i class="fa fa-search"></i></div>
            <input type="text" class="form-control" placeholder="Search the Fish" ng-model="searchFish">
          </div>
        </div>
      </form>
      

      A lot of that is Bootstrap markup to style our form beautifully, but the line we need to pay attention to is the input. This is where we define our ng-model to adjust the searchFish variable. Now as we type into that input box, you should see that variable change in the alert box above. With that variable bound and ready to go, all we have to do is apply it to our ng-repeat.

      Just like that, our filter will now be applied to the table. Go ahead and type into your filter box and see the table data change. You’ll also notice that the orderBy and filter will work together to find you the exact sushi roll that you want.

      Using some built-in Angular tools like ngRepeat, orderBy, filter, ngClick, and ngShow, we’ve been able to build a clean and fast table of data. This is a great look at the power that Angular has in building some great functionality into your own applications without too much work.

      Further Reading

      For more Angular goodness, here are some other great articles:

      Routing React Apps: The Complete Guide

      Introduction

      Routing is a key aspect of web applications (and even other platforms) could not be left out in React. We can make full-fleshed single-page applications with React if we harness the powers of routing. This does not have to be a manual process, we can make use of React-Router.

      In this guide, we will touch almost every aspect related to routing in React and there will be a demo so you will as well have something to play with.

      You do not need to have a high experience level to follow along. The basics of React components and how to use them are enough for you to follow along in this tutorial.

      You are not going to only learn how to route a React application but I will also show you the basics of tooling React using Babel, npm, and Webpack. Before we start building, let’s set that up and see what our folder structure will look like.

      First, create a new project:

      1. mkdir scotch-cars
      1. cd scotch-cars
      1. npm init

      Follow npm init wizard then install the following tooling dependencies:

      1. npm install webpack babel-loader babel-preset-es2015 babel-preset-react serve --save-dev

      We installed the following tooling dependencies:

      • webpack: Module loader/bundler for JavaScript.
      • babel-loader: Webpack loader for Babel. Babel transpiles ES6/ES7 to ES5.
      • babel-preset-es2015: ES6 preset for Babel. Babel core cannot handle transpiling tasks alone.
      • babel-preset-react: React preset for Babel. Just for Babel to understand React terms like JSX.
      • serve: HTTP server.

      Next is to configure our loader which is Webpack. Webpack is configured using a config file. So touch the file and update the config content as follows:

      1. touch webpack.config.js

      webpack.config.js

      var webpack = require('webpack');
      var path = require('path');
      
      var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
      var APP_DIR = path.resolve(__dirname, 'src/client/app');
      
      var config = {
        entry: APP_DIR + '/index.jsx',
        output: {
          path: BUILD_DIR,
          filename: 'bundle.js'
        },
        module : {
          loaders : [
            {
              test : /\.jsx?/,
              include : APP_DIR,
              loader : 'babel'
            }
          ]
        }
      };
      
      module.exports = config;
      

      The most important aspect of a Webpack config is the exported config object. The minimal code above just needs an entry point, entry which is where bundling needs to begin. It also requires an output, output which is where the bundled result is dumped, and then module, which defines what loaders should be used during the bundling process. In our case, babel is the loader we need.

      We need to explicitly tell Babel which presets it should make use of. You can do this with package.json or in a .babelrc file. .babelrc file is what you will see in most projects, so let’s follow that:

      1. touch .babelrc

      Define the presets:

      {
        "presets" : ["es2015", "react"]
      }
      

      To run Webpack we have to use a reference to the bin every time which would cause friction to our dev process. What we can do is set up scripts in the package.json to help us with that:

      package.json

      "scripts": {
         "watch" : "webpack -d --watch",
         "build" : "webpack",
         "serve" : "serve ./public"
       }
      

      The public directory will need an entry index.html which is very simple:

      ./public/index.html

      <html>
          <head>
              
              <link rel="stylesheet" href="style.css">
          </head>
          <body>
              
              <div id="container"></div>
              
              <script src="bundle.js"></script>
          </body>
      </html>
      

      Loads the bundle and defines the DOM element to mount our React app.

      Let us now define our folder structure so as to have a view of the task at hand before we start building:

      # Folder Structure
      |---public
      |------index.html # App entry
      |------style.css # Custom style
      |------bundle.js # Generated
      |---src # Components live here
      |------car
      |---------car.component.jsx
      |---------car-detail.component.jsx
      |------common
      |---------about.component.jsx
      |---------home.component.jsx
      |---------main.component.jsx
      |------index.jsx # Build entry
      |---.babelrc # Babel config file
      |---index.js
      |---package.json
      |---webpack.config.js # Webpack config gile
      

      The following are wireframes of what we are up to in this tutorial:

      Wireframes

      Now that we have got a simple environment for React to live in, the next step is to set it up for routing.

      React likes to keep things as simple as possible and that is why the core library just does exactly what React is about components. Routing, DOM rendering, and other logic are abstracted to a different library. To use routing, we have to pull down React, React Router, and React DOM:

      1. npm install react react-dom react-router --save

      A basic React component would look like this:

      ./src/index.jsx

      import React, { Component } from 'react';
      import { render } from 'react-dom';
      
      class Home extends Component {
          render(){
              return (<h1>Hi</h1>);
          }
      }
      
      render(<Home />, document.getElementById('container'));
      

      You can start watching and building these now with npm run watch. Then open another terminal and run npm run serve to start the server.

      Before routing

      Adding routing features to this app is very simple. Instead of rendering the Home component, we import Router and Route and use them to render the component:

      ./src/index.jsx

      import React, { Component } from 'react';
      import { render } from 'react-dom';
      
      import {Router, Route} from 'react-router';
      
      class Home extends Component {
          render(){
              return (<h1>Hi</h1>);
          }
      }
      
      render(
          <Router>
              <!--Each route is defined with Route-->
              <Route path="/" component={Home}/>
          </Router>,
          document.getElementById('container')
      );
      

      The path attribute defines the route URL and component attribute defines the component for this route.

      This kind of routing is different from what you might have seen in other UI frameworks and it is known as component routing. It is very easy to reason about because routes are also treated the same way components are treated. Routes are first-class components.

      After routing

      We discuss the ugly URL later in this article.

      You do not need routing if the only thing you want is a single path/page as our existing example shows. Let’s add more routes to the application:

      ./src/index.jsx

      import React, { Component } from 'react';
      import { render } from 'react-dom';
      
      import {Router, Route} from 'react-router';
      
      class Home extends Component {
          render(){
              return (<h1>Home Page</h1>);
          }
      }
      
      
      class Car extends Component {
          render(){
              return (<h1>Cars page</h1>);
          }
      }
      
      class About extends Component {
          render(){
              return (<h1>About page</h1>);
          }
      }
      
      render(
          <Router>
              <Route path="/" component={Home}/>
              <Route path="/cars" component={Car}/>
              <Route path="/about" component={About}/>
          </Router>,
          document.getElementById('container')
      );
      

      Compiled images of the three routes

      Let us do a little bit of refactoring and concern separation because that is what goes down in a real app:

      ./src/car/car.component.jsx

      import React, { Component } from 'react';
      
      class Car extends Component {
          render(){
              return (<h1>Cars page</h1>);
          }
      }
      
      export default Car
      

      ./src/common/home.component.jsx

      import React, { Component } from 'react';
      
      class Home extends Component {
          render(){
              return (<h1>Home Page</h1>);
          }
      }
      
      export default Home
      

      ./src/common/about.component.jsx

      import React, { Component } from 'react';
      
      class About extends Component {
          render(){
              return (<h1>About Page</h1>);
          }
      }
      
      export default About
      

      We just split the codes in to separate files while being guided by our predefined folder structure. Let’s assemble in the index file:

      ./src/index.jsx

      import React, { Component } from 'react';
      import { render } from 'react-dom';
      
      import {Router, Route} from 'react-router';
      
      import Home from './common/home.component.jsx'
      import About from './common/about.component.jsx'
      import Car from './car/car.component.jsx'
      
      render(
          <Router>
              <Route path="/" component={Home}/>
              <Route path="/cars" component={Car}/>
              <Route path="/about" component={About}/>
          </Router>,
          document.getElementById('container')
      );
      

      Nothing lost and we have a better app.

      This might be a better time to invite Bootstrap to the party. Of course, our app can’t remain that ugly. Import Bootstrap in the ./public/index.html and allow it to do its magic:

      ./public/index.html

      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
      

      Component routes are first-class components in React, so when it comes to parenting/ownership, the same rule applies. Our app is expected to have a navigation menu that is accessible by all the main routes. We can make another parent route for all the existing routes which will have the nav-bar:

      ./src/common/main.component.jsx

      import React, {Component} from 'react';
      
      class Main extends Component {
          render(){
              return(
                  <div>
                      <nav className="navbar navbar-default">
                          <div className="container-fluid">
                              <div className="navbar-header">
                                  <a className="navbar-brand" href="#">Scotch Cars</a>
                              </div>
                              <div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                                  <ul className="nav navbar-nav">
                                      <li className="active"><a href="#">Link <span className="sr-only">(current)</span></a></li>
                                      <li><a href="#">Link</a></li>
                                  </ul>
                              </div>
                          </div>
                      </nav>
                      <div className="container">
                          <!-- Mount child routes -->
                          {this.props.children}
                      </div>
                  </div>
              );
          }
      }
      
      export default Main
      

      In the route setup, add another Route component to render that wraps the rest of the routes;

      render(
          <Router>
              <Route component={Main}>
                  <Route path="/" component={Home}/>
                  <Route path="/cars" component={Car}/>
                  <Route path="/about" component={About}/>
              </Route>
          </Router>,
          document.getElementById('container')
      );
      

      Just like every other component, the contents of the child routes are poured out where ever {this.props.children} is found on the parent route.

      Route Prefixing

      Routes can be prefixed with React Router. Route prefixing is very common when building API endpoints where we have something like:

      1. https://example.com/api/cars

      api/ is the route prefix and we can do this with React Router for nested routes:

      <Router>
          <Route component={Main} path="app">
              <Route path="/" component={Home}/>
              <Route path="/cars" component={Car}/>
              <Route path="/about" component={About}/>
          </Route>
      </Router>
      

      The path attribute will prefix all the child routes path with its value and that gives us:

      1. /app
      2. /app/cars
      3. /app/cars

      Index Route

      There is another option to defining the root of your app (a.k.a index). IndexRoute is another component in React-Router that handles this:

      <Router>
          <Route path="/" component={Main} path="app">
              <IndexRoute component={Home} />
              <Route path="/cars" component={Car}/>
              <Route path="/about" component={About}/>
          </Route>
      </Router>
      

      You need to import the component from React-Router:

      import {Router, Route, IndexRoute} from 'react-router';
      

      History is a term that covers everything it takes to manage location, history, and URL in React-Router.

      Up till now, we have been dealing with an ugly URL. That is not the best React-Router can offer. React-Router offers three ways to manage URLs in React apps:

      At the moment our app defaults to hashHistory and that is what is responsible for the ugly URL. browserHistory is the recommended option for user consumption. We just need to tell React-Router to use browserHistoty:

      <Router>
          <Route path="/" component={Main} history={browserHistory}>
              <IndexRoute component={Home} />
              <Route path="/cars" component={Car}/>
              <Route path="/about" component={About}/>
          </Route>
      </Router>
      

      Import browserHistory from React-Router:

      import {Router, Route, IndexRoute, browserHistory} from 'react-router';
      

      You also need to set the base URL in the head of index.html before it works as expected:

      ./public/index.html

      <base href="/" />
      

      This works fine until you navigate to another page and reload:

      Image of a failing reload

      This shouldn’t surprise you though because now we are making a request back to the server which does not even handle a wildcard route. Let’s use express to fix this by creating a backend custom server with a wildcard route URL that takes us back to where we were when a reload happens:

      ./index.js

      const express = require('express')
      const path = require('path')
      const port = process.env.PORT || 3000
      const app = express()
      
      
      app.use(express.static(__dirname + '/public'))
      
      
      app.get('*', function (request, response){
          response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
      })
      
      app.listen(port)
      console.log("server started on port " + port)
      

      Now we can’t use serve again so we just run with Node:

      "scripts": {
         "watch" : "webpack -d --watch",
         "build" : "webpack",,
         "start" : "node index.js"
       }
      

      Our application is becoming more interesting and it is time to add some route links. We need to navigate with clicks and not changing URL values. Before we discuss how to add links, let’s populate our application with mock cars:

      ./src/car/car.component.jsx

      import React, { Component } from 'react';
      
      class Car extends Component {
          
          constructor(props){
              
              super(props);
              
              this.state = {
                  
                  cars: []
              };
          }
      
          componentDidMount(){
              
              const data = [
                  {
                      id: 1,
                      name: 'Honda Accord Crosstour',
                      year: '2010',
                      model: 'Accord Crosstour',
                      make: 'Honda',
                      media: 'http://www.example.com/honda/accord-crosstour/2010/oem/2010_honda_accord-crosstour_4dr-hatchback_ex-l_fq_oem_4_500.jpg',
                      price: '$16,811'
      
                  },
                  {
                      id: 2,
                      name: 'Mercedes-Benz AMG GT Coupe',
                      year: '2016',
                      model: 'AMG',
                      make: 'Mercedes Benz',
                      media: 'http://www.example.com/mercedes-benz/amg-gt/2016/oem/2016_mercedes-benz_amg-gt_coupe_s_fq_oem_1_717.jpg',
                      price: '$138,157'
      
                  },
                  {
                      id: 3,
                      name: 'BMW X6 SUV',
                      year: '2016',
                      model: 'X6',
                      make: 'BMW',
                      media: 'http://www.example.com/bmw/x6/2016/oem/2016_bmw_x6_4dr-suv_xdrive50i_fq_oem_1_717.jpg',
                      price: '$68,999'
                  },
                  {
                      id: 4,
                      name: 'Ford Edge SUV',
                      year: '2016',
                      model: 'Edge',
                      make: 'Ford',
                      media: 'http://www.example.com/ford/edge/2016/oem/2016_ford_edge_4dr-suv_sport_fq_oem_6_717.jpg',
                      price: '$36,275'
                  },
                  {
                      id: 5,
                      name: 'Dodge Viper Coupe',
                      year: '2017',
                      model: 'Viper',
                      make: 'Dodge',
                      media: 'http://www.example.com/dodge/viper/2017/oem/2017_dodge_viper_coupe_acr_fq_oem_3_717.jpg',
                      price: '$123,890'
                  }
              ];
              
              this.setState({cars: data});
          }
      
          render(){
              
              const carNode = this.state.cars.map((car) => {
                  return (
                      <a
                          href="#"
                          className="list-group-item"
                          key={car.id}>
                          {car.name}
                      </a>
                  )
              });
              return (
                  <div>
                      <h1>Cars page</h1>
                      <div className="list-group">
                          {carNode}
                      </div>
                  </div>
              );
          }
      }
      
      export default Car
      

      We updated our Car component to present a list of data. The data is a static array, no need for the complexity of request as this article is only about routing.

      Image with car lists

      With some static data available, let’s tackle this topic. Links in React routing work well with the anchor tag but this is not recommended. Link is a component that uses anchor internally and is the recommended way for displaying links because it plays nicer with React Router:

      <Link to="/">Home</Link>
      

      That is how links are used and the to property defines the path we want to navigate to on click just like href. Let’s update our Main component to apply links:

      ./src/common/common.component.jsx

      import React, {Component} from 'react';
      import { Link } from 'react-router';
      
      class Main extends Component {
          render(){
              return(
                  <div>
                      <nav className="navbar navbar-default">
                          <div className="container-fluid">
                              <div className="navbar-header">
                                  <a className="navbar-brand" href="#">Scotch Cars</a>
                              </div>
                              <div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                                  <ul className="nav navbar-nav">
                                      {}
                                      <li><Link to="/">Home</Link></li>
                                      <li><Link to="/cars">Cars</Link></li>
                                      <li><Link to="/about">About</Link></li>
                                  </ul>
                              </div>
                          </div>
                      </nav>
                      <div className="container">
                          {this.props.children}
                      </div>
                  </div>
              );
          }
      }
      
      export default Main
      

      We first import the Link component from React-Router then use the component for the navigation menu rather than <a>.

      After Link

      For a better user experience, it is a good practice to let the user know where he/she is at by indicating with a contrasting style on the active link. Let’s define a style in our style.css for that:

      ./public/style.css

      a.active {
          color: #000000 !important;
          text-decoration: underline !important;
      }
      

      Then we use React-Router’s activeClassName to active this style every time a respective link is activated:

       <li><Link to="/" activeClassName="active">Home</Link></li>
                                      <li><Link to="/cars" activeClassName="active">Cars</Link></li>
                                      <li><Link to="/about" activeClassName="active">About</Link></li>
      

      We need route parameters when requesting a single item or resource for a page. Take for instance:

      1. /cars/3
      2. /cars/honda-crosstour

      id and honda-crosstour are route parameters and we can use the value to retrieve a single car. During specification, the URLs are represented like this:

      1. /cars/:id
      2. /cars/:name

      We will make use of only id in this demo.

      First thing to do is define a route that should have a route parameter:

      render(
          <Router history={browserHistory}>
              <Route component={Main}>
                  <Route path="/" component={Home}/>
                  <Route path="/cars" component={Car}/>
                  {}
                  <Route path="/cars/:id" component={CarDetail}/>
                  <Route path="/about" component={About}/>
              </Route>
          </Router>,
          document.getElementById('container')
      );
      

      The spotlight is on:

      <Route path="/cars/:id" component={CarDetail}/>
      

      The path shows that a dynamic value is expected at the id placeholder. The CarDetail does not exist yet so let’s make that:

      ./src/car/car-detail.component.jsx

      import React, { Component } from 'react';
      
      class CarDetail extends Component {
          render(){
              return (<h1>{this.props.params.id}</h1>);
          }
      }
      
      export default CarDetail
      

      Like every other component but the parameter is accessed via props:

      this.props.params.id
      

      Don’t forget to import CarDetail in the root index

      Image of single resource

      Let’s use this ID to filter the cars array. Before we can do that we need to move the cars data array to a file that both Car and CarDetail component can have access to it. That should be the root then we can pass it down to the components as route props:

      import React, { Component } from 'react';
      import { render } from 'react-dom';
      
      import {Router, Route, IndexRoute, browserHistory} from 'react-router';
      
      import Main from './common/main.component.jsx'
      import Home from './common/home.component.jsx'
      import About from './common/about.component.jsx'
      import Car from './car/car.component.jsx'
      import CarDetail from './car/car-detail.component.jsx'
      
      const data = [
          {
              id: 1,
              name: 'Honda Accord Crosstour',
              year: '2010',
              model: 'Accord Crosstour',
              make: 'Honda',
              media: 'http://www.example.com/honda/accord-crosstour/2010/oem/2010_honda_accord-crosstour_4dr-hatchback_ex-l_fq_oem_4_500.jpg',
              price: '$16,811'
      
          },
          {
              id: 2,
              name: 'Mercedes-Benz AMG GT Coupe',
              year: '2016',
              model: 'AMG',
              make: 'Mercedes Benz',
              media: 'http://www.example.com/mercedes-benz/amg-gt/2016/oem/2016_mercedes-benz_amg-gt_coupe_s_fq_oem_1_717.jpg',
              price: '$138,157'
      
          },
          {
              id: 3,
              name: 'BMW X6 SUV',
              year: '2016',
              model: 'X6',
              make: 'BMW',
              media: 'http://www.example.com/bmw/x6/2016/oem/2016_bmw_x6_4dr-suv_xdrive50i_fq_oem_1_717.jpg',
              price: '$68,999'
          },
          {
              id: 4,
              name: 'Ford Edge SUV',
              year: '2016',
              model: 'Edge',
              make: 'Ford',
              media: 'http://www.example.com/ford/edge/2016/oem/2016_ford_edge_4dr-suv_sport_fq_oem_6_717.jpg',
              price: '$36,275'
          },
          {
              id: 5,
              name: 'Dodge Viper Coupe',
              year: '2017',
              model: 'Viper',
              make: 'Dodge',
              media: 'http://www.example.com/dodge/viper/2017/oem/2017_dodge_viper_coupe_acr_fq_oem_3_717.jpg',
              price: '$123,890'
          }
      ];
      
      
      render(
          <Router history={browserHistory}>
              <Route component={Main}>
                  <Route path="/" component={Home}/>
                  <Route path="/cars" component={Car} data={data}/>
                  <Route path="/cars/:id" component={CarDetail} data={data}/>
                  <Route path="/about" component={About}/>
              </Route>
          </Router>,
          document.getElementById('container')
      );
      

      We now have the data array in the index.jsx then we pass it down as a route prop:

      <Route path="/cars" component={Car} data={data}/>
      <Route path="/cars/:id" component={CarDetail} data={data}/>
      

      Finally, we update the Car component to use this data. The state is no longer needed so we can get rid of it and fetch the data from route props:

      ./src/car/car.component.jsx

      import React, { Component } from 'react';
      import { Link } from 'react-router';
      
      class Car extends Component {
          render(){
              
              const cars = this.props.route.data;
              
              const carNode = cars.map((car) => {
                  return (
                       <Link
                          to={"/cars/"+car.id}
                          className="list-group-item"
                          key={car.id}>
                          {car.name}
                      </Link>
                  )
              });
              return (
                  <div>
                      <h1>Cars page</h1>
                      <div className="list-group">
                          {carNode}
                      </div>
                  </div>
              );
          }
      }
      
      export default Car
      

      The fresh thing to learn is that we access data differently because the data was passed on to a route, not a component. Instead of:

      this.props.data
      

      we have:

      this.props.route.data
      

      We also used the opportunity to use Link instead of anchor tags for navigation which points:

      <Link
          to={"/cars/"+car.id}
          className="list-group-item"
          key={car.id}>
          {car.name}
      </Link>
      

      We can filter this data now with the parameter in CarDetail:

      import React, { Component } from 'react';
      
      class CarDetail extends Component {
          render(){
              
              const cars = this.props.route.data;
              
              const id = this.props.params.id;
              
              const car = cars.filter(car => {
                  if(car.id == id) {
                      return car;
                  }
              });
      
              return (
                  <div>
                      <h1>{car[0].name}</h1>
                      <div className="row">
                          <div className="col-sm-6 col-md-4">
                              <div className="thumbnail">
                                  <img src={car[0].media} alt={car[0].name} />
                              </div>
                          </div>
                          <div className="col-sm-6 col-md-4">
                             <ul>
                                 <li><strong>Model</strong>: {car[0].model}</li>
                                 <li><strong>Make</strong>: {car[0].make}</li>
                                 <li><strong>Year</strong>: {car[0].year}</li>
                                 <li><strong>Price</strong>: {car[0].price}</li>
                             </ul>
                          </div>
                      </div>
                  </div>
              );
          }
      }
      
      export default CarDetail
      

      Image of full detail

      Redirecting is quite an easy one. We can make use of browserHistory’s push method to redirect. For example, we can add a button to the details page that redirects to the list page on click:

      import React, { Component } from 'react';
      import { browserHistory } from 'react-router';
      
      class CarDetail extends Component {
          handleRedirect(){
              browserHistory.push('/cars');
          }
          render(){
              return(
                  
                          <div className="col-md-12">
                              <button className="btn btn-default" onClick={this.handleRedirect.bind(this)}>Go to Cars</button>
                          </div>
                  
              )
          }
      }
      

      It is a common practice to restrict users from accessing a particular resource because of limitations placed on their roles in the given app. We can’t afford to allow a buyer to have access to the admin dashboard where prices can be changed. Though this logic is something that MUST be handled backend but for a better user experience, it is also important on the frontend:

      const requireAuth = (nextState, replace) => {
          if (!auth.isAdmin()) {
              
              replace({ pathname: '/' })
          }
      }
      export const AdminRoutes = () => {
        return (
           <Route path="/admin" component={Admin} onEnter={requireAuth} />
        )
      }
      

      We are using the onEnter lifecycle event to listen to when this route will be hit. Once that happens, a check is run to determine if the authenticated user is an administrator or not.

      This was a long read but if you followed along, you have the basics of what you need to get going with React. This article does not just serve as a tutorial but also a reference for your day-by-day routing solutions in React with React Router.

      Easy Node Authentication: Setup and Local

      Note: This article is part of our Easy Node Authentication series.

      Introduction

      Authentication and logins in Node can be a complicated thing. Actually logging in for any application can be a pain. This article series will deal with authenticating in your Node application using the package Passport.

      Note: Updates

      Edit 11/18/2017: Updated to reflect Facebook API changes. Updating dependencies in package.json.
      Edit #1: Changed password hashing to be handled inside user model and asynchronously.
      Edit #2: Changed password hashing to be explicitly called. Helps with future tutorials.

      What we’ll be building:

      We will build an application that will have:

      • Local account logins and signups (using passport-local)
      • Facebook logins and registration (using passport-facebook)
      • Twitter logins and registration (using passport-twitter)
      • Google+ logins and registration (using oauth with passport-google-oauth)
      • Require login for certain routes/sections of your application
      • Creating a password hash for local accounts (using bcrypt-nodejs)
      • Displaying error messages (using flash with connect-flash. required since express 3.x)
      • Linking all social accounts under one user account
      • Allowing a user to unlink a specific social account

      Enough chit-chat. Let’s dive right into a completely blank Node application and build our entire application from scratch.

      Here’s what we’ll be building:

      And after a user has logged in with all their credentials:

      For this article, we’ll be focusing on setup and only local logins and registrations/signups. Since this is the first article and also deals with setting up our application, it will probably be one of the longer ones if not the longest. Sit tight for the duration of your flight.

      Setting Up Our Application

      To set up our base Node application, we’ll need a few things. We’ll set up our npm packages, node application, configuration files, models, and routes.

              - app
              ------ models
              ---------- user.js  <!-- our user model -->
              ------ routes.js    <!-- all the routes for our application -->
              - config
              ------ auth.js      <!-- will hold all our client secret keys (facebook, twitter, google) -->
              ------ database.js  <!-- will hold our database connection settings -->
              ------ passport.js  <!-- configuring the strategies for passport -->
              - views
              ------ index.ejs    <!-- show our home page with login links -->
              ------ login.ejs    <!-- show our login form -->
              ------ signup.ejs   <!-- show our signup form -->
              ------ profile.ejs  <!-- after a user logs in, they will see their profile -->
              - package.json      <!-- handle our npm packages -->
              - server.js         <!-- setup our application -->
      

      Go ahead and create all those files and folders and we’ll fill them in as we go along.

      We are going to install all the packages needed for the entire tutorial series. This means we’ll install all the packages needed for passport local, facebook, twitter, google, and the other things we need. It’s all commented out so you know what each does.

      package.json

          {
            "name": "node-authentication",
            "main": "server.js",
            "dependencies" : {
              "express" : "~4.14.0",
              "ejs" : "~2.5.2",
              "mongoose" : "~4.13.1",
              "passport" : "~0.3.2",
              "passport-local" : "~1.0.0",
              "passport-facebook" : "~2.1.1",
              "passport-twitter" : "~1.0.4",
              "passport-google-oauth" : "~1.0.0",
              "connect-flash" : "~0.1.1",
              "bcrypt-nodejs" : "latest",
      
              "morgan": "~1.7.0",
              "body-parser": "~1.15.2",
              "cookie-parser": "~1.4.3",
              "method-override": "~2.3.6",
              "express-session": "~1.14.1"
            }
          }
      

      Most of these are pretty self-explanatory.

      • Express is the framework.
      • Ejs is the templating engine.
      • Mongoose is object modeling for our MongoDB database.
      • Passport stuff will help us authenticating with different methods.
      • Connect-flash allows for passing session flashdata messages.
      • Bcrypt-nodejs gives us the ability to hash the password.

      I use bcrypt-nodejs instead of bcrypt since it is easier to set up in Windows.

      Now that we have all of our dependencies ready to go, let’s go ahead and install them:

      npm install With all of our packages ready to go, let’s set up our application in server.js.

      Let’s make all our packages work together nicely. Our goal is to set up this file and try to have it bootstrap our entire application. We’d like to not go back into this file if it can be helped. This file will be the glue for our entire application.

      server.js

          
          
          var express  = require('express');
          var app      = express();
          var port     = process.env.PORT || 8080;
          var mongoose = require('mongoose');
          var passport = require('passport');
          var flash    = require('connect-flash');
      
          var morgan       = require('morgan');
          var cookieParser = require('cookie-parser');
          var bodyParser   = require('body-parser');
          var session      = require('express-session');
      
          var configDB = require('./config/database.js');
      
          
          mongoose.connect(configDB.url); 
      
          
      
          
          app.use(morgan('dev')); 
          app.use(cookieParser()); 
          app.use(bodyParser()); 
      
          app.set('view engine', 'ejs'); 
      
          
          app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); 
          app.use(passport.initialize());
          app.use(passport.session()); 
          app.use(flash()); 
      
          
          require('./app/routes.js')(app, passport); 
      
          
          app.listen(port);
          console.log('The magic happens on port ' + port);
      

      We are going to comment out our passport configuration for now. We’ll uncomment it after we create that config/passport.js file.

      The path of our passport object is important to note here. We will create it at the very beginning of the file with var passport = require('passport');. Then we pass it into our config/passport.js file for it to be configured. Then we pass it to the app/routes.js file for it to be used in our routes.

      Now with this file, we have our application listening on port 8080. All we have to do to start up our server is:

      node server.js Then when we visit http://localhost:8080 we will see our application. (Not really right this moment since we have some more set up to do)

      Auto Refreshing: By default, Node.js doesn’t automatically refresh our server every time we change files. To do that we’ll use nodemon. Just install with: npm install -g nodemon and use with: nodemon server.js.

      Now, this won’t do much for our application since we don’t have our database configuration, routes, user model, or passport configuration set up. Let’s do the database and routes now.

      We already are calling this file in server.js. Now we just have to set it up.

      config/database.js

          module.exports = {
      
              'url' : 'your-settings-here' 
      
          };
      

      Fill this in with your own database. If you don’t have a MongoDB database lying around, I would suggest going to Modulus.io and grabbing one. Once you sign up (and you get a $15 credit for signing up), you can create your database, grab its connection URL, and place it in this file.

      You can also install MongoDB locally and use a local database. You can find instructions here: An Introduction to MongoDB.

      We will keep our routes simple for now. We will have the following routes:

      • Home Page (/)
      • Login Page (/login)
      • Signup Page (/signup)
      • Handle the POST for both login
      • Handle the POST for both signup
      • Profile Page (after logged in)

      app/routes.js

          module.exports = function(app, passport) {
      
              
              
              
              app.get('/', function(req, res) {
                  res.render('index.ejs'); 
              });
      
              
              
              
              
              app.get('/login', function(req, res) {
      
                  
                  res.render('login.ejs', { message: req.flash('loginMessage') });
              });
      
              
              
      
              
              
              
              
              app.get('/signup', function(req, res) {
      
                  
                  res.render('signup.ejs', { message: req.flash('signupMessage') });
              });
      
              
              
      
              
              
              
              
              
              app.get('/profile', isLoggedIn, function(req, res) {
                  res.render('profile.ejs', {
                      user : req.user 
                  });
              });
      
              
              
              
              app.get('/logout', function(req, res) {
                  req.logout();
                  res.redirect('/');
              });
          };
      
          
          function isLoggedIn(req, res, next) {
      
              
              if (req.isAuthenticated())
                  return next();
      
              
              res.redirect('/');
          }
      

      app.post: For now, we will comment out the routes for handling the form POST. We do this since passport isn’t set up yet.

      req.flash: This is the connect-flash way of getting flashdata in the session. We will create the loginMessage inside our passport configuration.

      isLoggedIn: Using route middleware, we can protect the profile section route. A user has to be logged in to access that route. Using the isLoggedIn function, we will kick a user back to the home page if they try to access http://localhost:8080/profile and they are not logged in.

      Logout: We will handle log out by using req.logout() provided by passport. After logging out, redirect the user to the home page.

      With our server running, we can visit our application in our browser athttp://localhost:8080. Once again, we won’t see much since we haven’t made our views. Let’s go do that now. (We’re almost to the authentication stuff, I promise).

      Here we’ll define our views for our home page, login page, and signup/registration page.

      Home Page views/index.ejs

      Our home page will just show links to all our forms of authentication.

      views/index.ejs

          <!doctype html>
          <html>
          <head>
              <title>Node Authentication</title>
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> 
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> 
              <style>
                  body        { padding-top:80px; }
              </style>
          </head>
          <body>
          <div class="container">
      
              <div class="jumbotron text-center">
                  <h1><span class="fa fa-lock"></span> Node Authentication</h1>
      
                  <p>Login or Register with:</p>
      
                  <a href="/login" class="btn btn-default"><span class="fa fa-user"></span> Local Login</a>
                  <a href="/signup" class="btn btn-default"><span class="fa fa-user"></span> Local Signup</a>
              </div>
      
          </div>
          </body>
          </html>
      

      Now if we visit our app in our browser, we’ll have a site that looks like this:

      Here are the views for our login and signup pages also.

      Login Form views/login.ejs

      views/login.ejs

          <!doctype html>
          <html>
          <head>
              <title>Node Authentication</title>
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> 
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> 
              <style>
                  body        { padding-top:80px; }
              </style>
          </head>
          <body>
          <div class="container">
      
          <div class="col-sm-6 col-sm-offset-3">
      
              <h1><span class="fa fa-sign-in"></span> Login</h1>
      
              
              <% if (message.length > 0) { %>
                  <div class="alert alert-danger"><%= message %></div>
              <% } %>
      
              
              <form action="/login" method="post">
                  <div class="form-group">
                      <label>Email</label>
                      <input type="text" class="form-control" name="email">
                  </div>
                  <div class="form-group">
                      <label>Password</label>
                      <input type="password" class="form-control" name="password">
                  </div>
      
                  <button type="submit" class="btn btn-warning btn-lg">Login</button>
              </form>
      
              <hr>
      
              <p>Need an account? <a href="/signup">Signup</a></p>
              <p>Or go <a href="/">home</a>.</p>
      
          </div>
      
          </div>
          </body>
          </html>
      

      Signup Form views/signup.ejs

      views/signup.ejs

          <!doctype html>
          <html>
          <head>
              <title>Node Authentication</title>
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> 
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> 
              <style>
                  body        { padding-top:80px; }
              </style>
          </head>
          <body>
          <div class="container">
      
          <div class="col-sm-6 col-sm-offset-3">
      
              <h1><span class="fa fa-sign-in"></span> Signup</h1>
      
              
              <% if (message.length > 0) { %>
                  <div class="alert alert-danger"><%= message %></div>
              <% } %>
      
              
              <form action="/signup" method="post">
                  <div class="form-group">
                      <label>Email</label>
                      <input type="text" class="form-control" name="email">
                  </div>
                  <div class="form-group">
                      <label>Password</label>
                      <input type="password" class="form-control" name="password">
                  </div>
      
                  <button type="submit" class="btn btn-warning btn-lg">Signup</button>
              </form>
      
              <hr>
      
              <p>Already have an account? <a href="/login">Login</a></p>
              <p>Or go <a href="/">home</a>.</p>
      
          </div>
      
          </div>
          </body>
          </html>
      

      Authenticating With Passport Locally

      Finally! We have finally set up our application and have gotten to the authentication part. Don’t worry. The rest of the authentication articles in this tutorial series will use the same base so we won’t have to set up our application again.

      So far we have installed our packages, set up our application, connected to our database, created our routes, and created our views.

      Now we will create our user model, configure passport for local authentication, and use our configured passport to process our login/signup forms.

      We will create our user model for the entire tutorial series. Our user will have the ability to be linked to multiple social accounts and to a local account. For local accounts, we will be keeping email and password. For the social accounts, we will be keeping their id, token, and some user information.

      You can change these fields out to be whatever you want. You can authenticate locally using username and password (passport-local actually uses username by default but we’ll change that to email).

      app/models/user.js

          
          var mongoose = require('mongoose');
          var bcrypt   = require('bcrypt-nodejs');
      
          
          var userSchema = mongoose.Schema({
      
              local            : {
                  email        : String,
                  password     : String,
              },
              facebook         : {
                  id           : String,
                  token        : String,
                  name         : String,
                  email        : String
              },
              twitter          : {
                  id           : String,
                  token        : String,
                  displayName  : String,
                  username     : String
              },
              google           : {
                  id           : String,
                  token        : String,
                  email        : String,
                  name         : String
              }
      
          });
      
          
          
          userSchema.methods.generateHash = function(password) {
              return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
          };
      
          
          userSchema.methods.validPassword = function(password) {
              return bcrypt.compareSync(password, this.local.password);
          };
      
          
          module.exports = mongoose.model('User', userSchema);
      

      Our model is done. We will be hashing our password within our user model before it saves to the database. This means we don’t have to deal with generating the hash ourselves. It is all handled nicely and neatly inside our user model.

      Let’s move on to the important stuff of this article: authenticating locally!

      Configuring Passport for Local Accounts

      All the configuration for passport will be handled in config/passport.js. We want to keep this code in its own file away from our other main files like routes or the server file. I have seen some implementations where passport will be configured in random places. I believe having it in this config file will keep your overall application clean and concise.

      So far, we have created our passport object in server.js, and then we pass it to our config/passport.js file. This is where we configure our Strategy for local, facebook, twitter, and google. This is also the file where we will create the serializeUser and deserializeUser functions to store our user in session.

      I would highly recommend going to read the passport docs to understand more about how the package works.

      We will be handling login and signup in config/passport.js. Let’s look at signup first.

      config/passport.js

          
          var LocalStrategy   = require('passport-local').Strategy;
      
          
          var User            = require('../app/models/user');
      
          
          module.exports = function(passport) {
      
              
              
              
              
              
      
              
              passport.serializeUser(function(user, done) {
                  done(null, user.id);
              });
      
              
              passport.deserializeUser(function(id, done) {
                  User.findById(id, function(err, user) {
                      done(err, user);
                  });
              });
      
              
              
              
              
              
      
              passport.use('local-signup', new LocalStrategy({
                  
                  usernameField : 'email',
                  passwordField : 'password',
                  passReqToCallback : true 
              },
              function(req, email, password, done) {
      
                  
                  
                  process.nextTick(function() {
      
                  
                  
                  User.findOne({ 'local.email' :  email }, function(err, user) {
                      
                      if (err)
                          return done(err);
      
                      
                      if (user) {
                          return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
                      } else {
      
                          
                          
                          var newUser            = new User();
      
                          
                          newUser.local.email    = email;
                          newUser.local.password = newUser.generateHash(password);
      
                          
                          newUser.save(function(err) {
                              if (err)
                                  throw err;
                              return done(null, newUser);
                          });
                      }
      
                  });
      
                  });
      
              }));
      
          };
      

      We have now provided a strategy to passport called local-signup. We will use this strategy to process our signup form. Let’s open up our app/routes.js and handle the POST for our signup form.

      app/routes.js

          ...
      
              
              app.post('/signup', passport.authenticate('local-signup', {
                  successRedirect : '/profile', 
                  failureRedirect : '/signup', 
                  failureFlash : true 
              }));
      
          ...
      

      That’s all the code we need for the route. All of the heavy-duty stuff lives inside of config/passport.js. All we have to set here is where our failures and successes get redirected. Super clean.

      There is also much more you can do with this. Instead of specifying a successRedirect, you could use a callback and take more control over how your application works. Here is a great stackoverflow answer on error handling. It explains how to use done() and how to be more specific with your handling of a route.

      Testing Signup

      With our passport config finally laid out, we can uncomment that line in our server.js. This will load our config and then we can use our signup form.

      server.js

          ...
      
              
              require('./config/passport')(passport); 
      
          ...
      

      Now that we have passport, our routes, and our redirects in place, let’s go ahead and test our signup form. In your browser, go to http://localhost:8080/signup and fill out your form.

      If all goes according to plan, you should be logged in, your user saved in the session, and you are redirected to the /profile page (the profile page will show nothing right now since we haven’t defined that view).

      If we look in our database, we’ll also see our user sitting there cozily with all the credentials we created for him.

      Exploring Your Database: I use Robomongo to see what’s in my database. Just download it and connect to your database to see your new users after they signup!

      With users able to sign up, let’s give them a way to log in.

      This will be very similar to the signup strategy. We’ll add the strategy to our config/passport.js and the route in app/routes.js.

      config/passport.js

          ...
      
              
              
              
              
              
      
              passport.use('local-login', new LocalStrategy({
                  
                  usernameField : 'email',
                  passwordField : 'password',
                  passReqToCallback : true 
              },
              function(req, email, password, done) { 
      
                  
                  
                  User.findOne({ 'local.email' :  email }, function(err, user) {
                      
                      if (err)
                          return done(err);
      
                      
                      if (!user)
                          return done(null, false, req.flash('loginMessage', 'No user found.')); 
      
                      
                      if (!user.validPassword(password))
                          return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); 
      
                      
                      return done(null, user);
                  });
      
              }));
      
          };
      

      We have now provided a strategy to passport called local-login. We will use this strategy to process our login form. We can check if a user exists, if the password is wrong, and set flash data to show error messages. Let’s open up our app/routes.js and handle the POST for our login form.

      app/routes.js

          ...
      
              // process the login form
              app.post('/login', passport.authenticate('local-login', {
                  successRedirect : '/profile', // redirect to the secure profile section
                  failureRedirect : '/login', // redirect back to the signup page if there is an error
                  failureFlash : true // allow flash messages
              }));
      
          ...
      

      If you try to log in with a user email that doesn’t exist in our database, you will see the error. The same goes for if your password is wrong.

      Now we have functional signup and login forms. If a user is successful in authenticating they will be redirected to the profile page. If they are not successful, they will go home. The last thing we need to do is make our profile page so that those that are lucky enough to signup (all of us?) will have an exclusive place of our site all to themselves.

      views/profile.ejs

          <!doctype html>
          <html>
          <head>
              <title>Node Authentication</title>
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
              <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
              <style>
                  body        { padding-top:80px; word-wrap:break-word; }
              </style>
          </head>
          <body>
          <div class="container">
      
              <div class="page-header text-center">
                  <h1><span class="fa fa-anchor"></span> Profile Page</h1>
                  <a href="/logout" class="btn btn-default btn-sm">Logout</a>
              </div>
      
              <div class="row">
      
                  
                  <div class="col-sm-6">
                      <div class="well">
                          <h3><span class="fa fa-user"></span> Local</h3>
      
                              <p>
                                  <strong>id</strong>: <%= user._id %><br>
                                  <strong>email</strong>: <%= user.local.email %><br>
                                  <strong>password</strong>: <%= user.local.password %>
                              </p>
      
                      </div>
                  </div>
      
              </div>
      
          </div>
          </body>
          </html>
      

      After a user logs in, they can see all their information. It is grabbed from the session and passed to our view in the app/routes.js file. We will also provide a link to log out.

      There you have it! We’ve built a brand new application from scratch and have the ability to let users signup/register and log in. We even have support for flash messages, hashing passwords, and requiring a login for some sections of our site using route middleware.

      Coming up next we’ll be looking at how to take this same structure, and use passport to authenticate with Facebook, Twitter, and Google. After that, we’ll look at how we can get all these things working together in the same application. Users will be able to log in with one type of account, and then link their other accounts.

      As always, if you see any ways to improve this or need any clarification, sound off in the comments and we’ll respond pretty close to immediately… pretty close.