CSCI 421 - Lecture 7

Instructor's Class Notes

  1. Chapter 9 (Part 3:9) - Building a Single-Page Application with Angular: Foundations
    1. Setting up the Application - Make sure to update your application's app.js to include the newly created app_client directory:
      
      app.use(express.static(path.join(__dirname, 'public')));
      app.use(express.static(path.join(__dirname, 'app_client')));               
                      
    2. Add sending of index.html to the browser - In app.js you need to send your front-end index.html file that includes HTML and Angular directives to the browser. That is performed with the following code:
      
      app.use('/api', routesApi);
      
      // Added per Lab 5 - Angular
      app.use(function(req, res) {
        res.sendFile(path.join(__dirname, 'app_client', 'index.html'));
      });                
                      
                      
    3. Creating the Angular app file - An Angular application file must be developed and placed in your app_client directory. You can use a file name of app.js, but a more application specific file name might be more wise, say for example bloggerApp.js. Within that file you hve to declare your Angular module, as so:
      
      var app = angular.module('bookApp', []);                
                      
    4. Download and use Angular.js files - At a miniumum, your SPA will require angular.min.js and angular-route.min.js. Find these from a reputable sourde and download them to the lib directory of your app_client directory for use.
    5. Add an Angular Route Provider - The ngRoute module provides the basis for a router that will map your applications screens to different controllers and HTML templates. See section 9.2.2 of the book.

      Example:
      
      var app = angular.module('bookApp', ['ngRoute']);
      
      //*** Router Provider ***
      app.config(function($routeProvider) {
        $routeProvider
            .when('/', {
      	      templateUrl: 'pages/home.html',
      		  controller: 'HomeController',
      		  controllerAs: 'vm'
      		  })
      
            .when('/book-list', {
      	      templateUrl: 'pages/book-list.html',
      		  controller : 'ListController',
      		  controllerAs: 'vm'
      		  })
      
            .when('/book-add', {
      	      templateUrl: 'pages/book-add.html',
      		  controller: 'AddController',
      		  controllerAs: 'vm'
      		  })
                
              .when('/book-edit/:id', {
      	      templateUrl: 'pages/book-edit.html',
      		  controller: 'EditController',
      		  controllerAs: 'vm'
      		  })
      
            .otherwise({redirectTo: '/'});
          });
                          
    6. Adding Views, Controllers and Services - Now, this is where the book gets complicated and the examples and sample code a bit fuzzy. You can develop your own code without services, if you wish, to keep it simple. Regardless, you will have to learn Angular directives that go in your HTML file(s), ng-view, ng-repeat, ng-submit, etc. The controllers act and work much like the controllers written under Express.
    7. Use ViewModels - In your controllers, use the ControlAs attribute and define a ViewModel and name it vm. The ViewModel is an object that passes between the controller code and your HTML page code and maintains state and information bindings.
    8. Services, Directives and Filters...oh my! - Please read the book to better understand these facilites and use them in your labs if you desired (though they are NOT required).
    9. IIFE and uglify, etc - The book describes and shows the use of IIFE and uglify. These are good for production code and larger applications, but not required for the labs you will be developing.
    10. $http - The $http client module is all that is needed for executing a REST API, and it supports get, post, put and delete. It is rather simple to use (see the book and on-line examples). The one thing to be wary of is that the client object itself must be pasaed into your controller methods in order to be accessed.
    11. HTML code - The HTML for an Angular SPA is relatively straightforward and for most simple apps all the HTML code will be in one file, index.html in the app_client directory, and that file will have your navigation and an Angular template for each 'page' of your app. Take particular note of the bold HTML tags below and recognize that the ng-view directive in one div is critical to bind your page to your route provider:
      
      <!doctype html>
      <html ng-app="bookApp">
        <head>
          <script src="/js/angular.min.js"></script>
          <script src="/js/angular-route.min.js"></script>  
          <script src="/js/angular-ui-router.min.js"></script>    
          <link rel='stylesheet' href='/stylesheets/style.css' />
          <link rel="stylesheet" href="/css/bootstrap.min.css">
          <link rel="stylesheet" href="/css/fontawesome-all.css">
        </head>
        <body>
        
          <!-- Navigation -->  
          <nav class="navbar fixed-top navbar-expand-sm navbar-dark bg-primary">
          <a class="navbar-brand" href="#/"My Books</a>
          <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
              <div class="navbar-nav">
              <a class="nav-item nav-link active" href="#/book-list"List Books</a>
              a class="nav-item nav-link active" href="#/book-add"Add Books</a>
              </div>
          </div>
          </nav> 
            
          <!-- Angular Templates -->  
          <script type="text/ng-template" id="pages/home.html">
            <p></p>
            <h2>{{vm.pageHeader.title}}</h2>
            <h4>{{vm.message}}</h4>
          </script>
            
          <script type="text/ng-template" id="pages/book-list.html">
            <p></p>
            <div ng-repeat="book in vm.books">
            <div class="card border-primary" style="width: 50%"> 
                  <div class="card-header">
                  </div>
                  <div class="card-body">
                      <h5 class ="card-title">{{book.bookTitle}</h5>
                  </div>
                  <div class="card-footer">
                      <div class = "col-sm">
                         <ul class="nav justify-content-end nav-pills card-header-pills">
                           <li class="nav-item">
                               <a class="nav-link" href="#/book-edit/{{book._id}}" <i class="fas fa-edit"</i></a>
                           </li>
                           <li class="nav-item">
                               <a class="nav-link" href="#/book-delete/{{book._id}}" <i class="fas fa-trash-alt"></i></a>
                           </li>
                         </ul>
                  </div>	
                  </div>
            </div>
            <p>               
            </div>
          </script>
          
          <script type="text/ng-template" id="pages/book-edit.html">
              <p></p>
              <div class="card border-primary" style="width: 50%">  
              <form name="userForm" ng-submit="vm.submit()" ng-controller="EditController" style="padding: 20px">
                  <div class="form-group">
                      <label for="summary" class="text-primary">Book Title</label>
                      <input class="form-control" id="bookTitle" name="bookTitle" value="{{vm.book.bookTitle}}">
                      <label for="detail" class="text-primary">Book Text</label>
                      <textarea class="form-control" id="bookText" name="bookText" rows="3">{{vm.book.bookText}}</textarea>
                  </div>
                  <input type="submit" class="btn btn-primary" value="Save Book">
              </form> 
              </div>
          </script>  
      
          <!-- Angular View (dynamic content goes here) -->  
          <div ng-view></div>
          
      <script src="/js/bookApp.js"></script>
      </body>
      </html>