Categories
Programming

Single Page Web App using AngularJs Routing

In traditional web apps, server would process the data, generate HTML and clients would just render the html and run some sprinkled javascript in the page.

With client systems (phones, computers) getting more powerful it is now possible to push more processing to clients. Single Page Apps take benefit of this phenomenon.

As name suggests, SPAs just load stub html once and instead of going to server for every page, it only makes requests for data. Once data is available, based on state of application, necessary views are rendered. This gives nice illusion of full multipage application within one page.

Examples of Single Page Web Applications

  • Netflix
  • AirBNB
  • Google Maps
  • Pinterest
  • Facebook
  • Twitter

In previous article, Part-1 of single page web app I used angular without routing. Now, in Part-2 I developed single page app with angular routing.

Code with Angular Routing:

JavaScript code is in ‘app.js’. In this first we must add the ‘ngRoute‘ as a dependency in the application module. If we want to navigate to different pages in our application, but we also want the application to be a SPA (Single Page Application), with no page reloading, we can use the ngRoute module.

var app = angular.module("myApp", ["ngRoute"]);

In this example, we don’t have backend store to persist the data.
So I am using factory variable ‘AppData‘ to pass state between multiple controllers.

app.factory('AppData', function () {
    return {
        products: [{ title: 'Mozzarella Cheese', desc: 'Ten Count of Sargento Shredded Whole Milk Mozzarella Natural Cheese' }]
    };
});

Now our application has access to the route module, which provides the ‘$routeProvider'. Use the $routeProvider to configure different routes in our application:

app.config(function ($routeProvider) {
    $routeProvider

        // route for the home page
        .when('/', {
            templateUrl: '/home.html',
            controller: 'mainController'
        })

        // route for the about page
        .when('/:id', {
            templateUrl: '/about.html',
            controller: 'aboutController'
        })

        .otherwise({ redirectTo: '/' });

});

We need to define a controller for each view and use ‘$location' service, it has methods which return information about the location of the current web page. Let’s add controllers:

First add ‘mainController‘, in this I have written the code for add, remove and display the particular product to our list.

app.controller('mainController', function ($scope, $location, AppData) {

    // create a message to display in our view
    $scope.message = 'Product List App';

    // Add product to list
    $scope.product = { title: "", desc: "" };
    $scope.products = AppData.products;

    $scope.addItem = function () {
        $scope.products.push($scope.product);
        $scope.product = { title: "", desc: "" };
        $scope.showCur = false;
    }

    // Remove product from list 
    $scope.removeItem = function (x) {
        $scope.products.splice(x, 1);
    }

    // Display particular product-description
    $scope.displayItem = function (x) {
        $location.path("/" + x);
    }

});

Next add ‘aboutController‘, in this we also need to add code to add product and go back on main page.

app.controller('aboutController', function ($scope, $location, AppData) {

    // create a message to display in our view
    $scope.message = 'Product List App';

    $scope.products = AppData.products;
    const id = parseInt($location.url().substring(1));
    $scope.cur = $scope.products[id];

    // Add product to list
    $scope.product = { title: "", desc: "" };
    $scope.addItem = function () {
        $scope.products.push($scope.product);
        $location.path("/");
    }

    // back button result
    $scope.backDisp = function () {
        $location.path("/");
    }

});

In ‘index.html‘, we must include the AngularJS Route module. Add links to the html that will help in navigating to the configured pages. Use ‘ng-view‘ directive, this will be the placeholder for all views provided by the route.

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <!-- load Angular -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
    <!-- Routing -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
    <!-- load Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
        integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>

<body>
    <header>
        <nav class="navbar navbar-default">
            <div class="container">
                <div class="navbar-header">
                    <a class="navbar-brand" href="/">Single Page Application Using AngularJS Routing</a>
                </div>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#!"><i class="fa fa-home"></i>Home</a></li>
                </ul>
            </div>
        </nav>
    </header>
    <!-- Main Content AND Injected Views -->
    <div ng-view></div>
    <!-- JavaScript -->
    <script src="app.js"></script>
</body>
</html>

Configure the page ‘home.html‘ :

<div class="jumbotron text-center">
    <div class="container">
        <h1 class="page-header">{{ message }}</h1>
        <form>
            Your Item:<br />
            <input class="form-control form-control-lg" type="text" placeholder="Item" ng-model="product.title"><br />
            Description of Item:
            <textarea class="form-control" id="exampleFormControlTextarea1" rows="5" placeholder="Description"
                ng-model="product.desc"></textarea>
            <br />
            <button type="button" class="btn btn-primary btn-lg btn-block" ng-click="addItem()">Add</button>
            <br />
            <br />
            <h2>Item: {{product.title}} </h2>
            <br />
            <h2>Description: {{product.desc}} </h2>
            <br />
            <ul class="list-group" ng-show="!showCur">
                <li class="d-flex list-group-item list-group-item-info" ng-repeat="product in products">
                    <span class="col-sm-8">{{product.title + " - " + product.desc}}</span>
                    <button type="button" class="btn btn-dark col-sm-2" ng-click="removeItem($index)">Delete</button>
                    <span> </span>
                    <button type="button" class="btn btn-dark col-sm-2" ng-click="displayItem($index)">Open</button>
                </li>
            </ul>
            <div ng-show="showCur">
                {{cur.title + " - " + cur.desc}}
                <br />
                <button type="button" class="btn btn-secondary btn-lg btn-block" ng-click="backDisp()">Back</button>
            </div>
        </form>
    </div>
</div>

Configure the page ‘about.html‘ :

<div class="jumbotron text-center">
    <div class="container">
        <h1 class="page-header">{{ message }}</h1>
        <form>
            Your Item:<br />
            <input class="form-control form-control-lg" type="text" placeholder="Item" ng-model="product.title"><br />
            Description of Item:
            <textarea class="form-control" id="exampleFormControlTextarea1" rows="5" placeholder="Description"
                ng-model="product.desc"></textarea>
            <br />
            <button type="button" class="btn btn-primary btn-lg btn-block" ng-click="addItem()">Add</button>
            <br />
            <br />
            <h2>Item: {{product.title}} </h2>
            <br />
            <h2>Description: {{product.desc}} </h2>
            <br />
            {{cur.title + " - " + cur.desc}}
            <br />
            <button type="button" class="btn btn-secondary btn-lg btn-block" ng-click="backDisp()">Back</button>
        </form>
    </div>
</div>

That’s it! For more details you can follow my Glitch projects.

Practice Code in Glitch: