Single Page Application với ngRoute của AngularJS

Các ứng dụng Single Page Application đang dần trở nên phổ biến hơn. Bài viết này mình xin trình bày về Routing Single Page với module ngRoute của Angularjs.

Trước hết Single Page Application(SPA) là gì?

SPA là 1 trang web hay 1 ứng dụng web, khi tất cả những thao tác xử lý đều được diễn ra trên 1 trang duy nhất.sqp.png

Với các trang web truyền thống, khi user request 1 trang web thì server sẽ tính toán và trả về trang web đó dưới dạng mã HTML và hầu như không có bất kỳ sự liên kết nào giữa 2 yêu cầu gần nhau. Do đó khi có nhiều yêu cầu được đưa ra thì quá trình tính toán sẽ diễn ra lâu hơn. Và trả về 1 trang web hoàn trỉnh.

Còn với SPA thì khi user request lần đầu thì server sẽ tính toàn và trả về trang web dưới dạng HTML. tuy nhiên ở những lần yêu cầu tiếp theo thì client chỉ phải request nhưng phần nào 1 cần (AJAX) và server sẽ sẽ trả dữ liệu với dạng JSON sẽ giúp ngắn thời gian truyền tải. Hay nói cách khác SPA chỉ load phần trang cần thiết.

Hiện nay có có khá nhiều framework sử dụng SPA như AnguarJS, BackBonJS, SailJS.

ở bài này mình xin trình bày SPA trên framwork AngularJS

Trong AngularJS cung cấp cho bạn 1 module là ngRoute. ngRoute sẽ cung cấp các routing, deep linking và các directives cho các ứng dụng angularJS.

Để sử dụng ngRoute chúng ta cần include nó trong file html

<script src="angular-route.js">

Sau đó khai báo ngRoute là module trong angular application

angular.module('myApp', ['ngRoute']);

  • ngView directive ngView directive bao gồm các template đã được rendered của route hiện tại vào trong file layout chính. mỗi lần thay đổi route hiện tại thì view đi cùng với nó cũng thay đổi để phù hợp với $route service

Trong angular bạn cần phải định nghĩa ngView directive 1 lần (đây là phần lưu giữ các views và lưu ý trong SPA thì ngView directive chỉ được sử dụng 1 lần duy nhất.)

Có 3 cách để bạn khai báo 1 directive như mình đã nói ở các bài trước rồi:

1, <div ng-view></div # attribute

2, <ng-view></ng-view> # element

3, <div class="ng-view"></div> #class

Dùng để config route. Khi $routeProvider được khai báo chúng ta có thể sử dụng các service mà nó cung cấp là $route service và $routeParams service.

   angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'pages/home.html',
        controller: 'MainController'
      })
      .when('/about', {
        template: 'This is about page!!!'
      })
      .otherwise({
        redirectTo: '/'
      })
  });

Như đoạn code trên $routeProvider sử dụng phương thức $routeProvider.when() để truyền 1 URL với 1 view. Trong khi đó phương thức $routeProvider.otherwise() sẽ trả lại 1 view khi url hiện tại không khớp với bất kỳ các URL nào đc đưa ra. Nó như dạng if else vậy.

Đi sâu vào hàm $routeProvider ta có hàm when() chúng bao gồm 2 tham số là : route path và 1 object JavaScript when(path, route)

1, path: có dạng string nó là địa chỉ url có thể chứa các tham số. Các tham số được lưu trong $routeParams.

2, route: là 1 object JavaScript bao gồm teamplateURL và template. ở bài trước khi mình đề cập về các directive trong AngularJS mình có trình bài về teamplateURL và teamplate rồi.

Hiểu 1 cách đơn giản thì teamplateURL là 1 đường dẫn or 1 function dẫn tới 1 file HTML.

   angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'pages/home.html',
        controller: 'MainController'
      })
   });

còn template là 1 đoạn html or 1 function trả về 1 teamplate html.

   angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'pages/home.html',
        template: '<h2>Hello, I am html template.</h2>'
      })
   });

(Note: template sẽ được ưu tiên hơn templateUrl)

Trong $routeProvider còn có 3, controller: dùng để điểu khiên view tương ứng với các teamplate được khai báo trong template hoặc templateUrl 4, controllerAs: là alias name của controller. chúng sẽ coi controller như 1 class

VD:

    angular.module('myApp', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/about', {
        templateUrl: 'about.html',
        controller: 'AboutCtrl',
        controllerAs: 'about'
      })
  })
  .controller('AboutCtrl', function() { // don't use $scope
    this.flash = 'Content will be display here. :)'; // use this instead of $scope
  });

và có file html about.html

    <h2>About page</h2>
    <p>{{ about.flash }}</p>

5, rediectTo: chuyển đến 1 URL cụ thể

VD:

Ta tạo 3 file html: index.html, about.html, contact.html, contact-detail.html, script.js

index.html

<!DOCTYPE html>
<html ng-app="spaApp">
  <head>
    <title>Simple SPA</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-route.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <header>
      <nav class="navbar navbar-default" role="navigation">
        <div class="container-fluid">
          <div class="navbar-header">
            <a class="navbar-brand" href="#">Simple Routing</a>
          </div>

          <ul class="nav navbar-nav nav-right">
            <li><a href="#home">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</li>
         </ul>
       </div>
     </nav>
   </header>

   <div id="main" class="container-fluid">
    <div ng-view></div>
   </div>
    <div ng-view></div>
  </body>
</html>

contact.html

  <h3>{{flash}}</h3>
  <ul class="list-group">
    <li class="list-group-item" ng-repeat="user in users">
      <a href="#contact/{{user.id}}">{{user.name}}</a>
    </li>
  </ul>

contact-detail.html

 <h3>This is detail for contact #{{userId}}</h3>

about.html

  <h2>About page</h2>
  <p>{{ about.flash }}</p>
angular.module('spaApp', ['ngRoute'])
  .config(['$routeProvider',
    function($routeProvider) {
      $routeProvider
        .when('/home', {
          //templateURL
          template: "<h1>This is Home Page</h1>"
        })
        .when('/contact', {
          //templateURL
          templateUrl: 'contact.html',
          controller: 'ContactController'
        })
        .when('/contact/:userId', {
          // $routeParams
          templateUrl: 'contact-detail.html',
          controller: 'ContactDetailController'
        })
        .when('/about', {
          templateUrl: 'about.html',
          controller: 'AboutCtrl',
          //use controler alias
          controllerAs: 'about'
        })
        .otherwise({
          redirectTo: '/home'
        });
    }
  ])
  .controller('HomeController', function($scope) {
    $scope.flash = 'This is Home Page';
  })
  .controller('ContactController', function($scope) {
    $scope.flash = 'This thi Contact';
    $scope.users = [
      { id: '1', name: 'User1'},
      { id: '2', name: 'User2'},
      { id: '3', name: 'User3'}
    ];
  })
  .controller('ContactDetailController', ['$scope', '$routeParams',
    function($scope, $routeParams) {
      $scope.userId = $routeParams.userId;
    }
  ]);
  .controller("AboutController", function(){
    this.flash = "This is About Page"
  })

  • Services trong ngRoute:

1, reload(): cho phép tải lại route hiện tại ngay cả khu url không thay đổi

  app.controller('AppController', ['$scope', '$route', function ($scope, $route) {
    $scope.reloadRoute = function () {
      $route.reload();
    };
  }]);

2, updateParams(newParams): cho phép thay thế các tham số của URL bằng các tham số trong newParams

  .when('/contact/:userId', {
    // $routeParams
    template: "<h3>test:{{userId}}</h3><button ng-click='reloadRoute()'>reloadRoute</button>",
    templateUrl: 'contact-detail.html',
    controller: 'ContactDetailController'
  })

  .controller('ContactDetailController', ['$scope', '$routeParams',
    function($scope, $routeParams) {
      $scope.userId = $routeParams.userId;

      $scope.reloadRoute = function(){
        $route.updateParams({userId: 4});
      }
    }
  ]);
  • Events Phần cuối trong $routeProvider là events: 1, $routeChangeStart: được khởi tạo khi route thay đổi. Nó sẽ giúp giải quyết tất cả các phụ thuộc cần thiết để thay đổi route. 2, $routeChangeSuccess: được khởi tạo khi $routeChangeStart làm xong công việc của. Nó sẽ gọi đến controller và render view tương ứng. 3, $routeChangerErro: được khởi tạo khi $routeChangeStart không giải quyết được tất cả các phụ thuộc cần thiết và sẽ không khởi tạo $routeChangeSuccess.

Vậy là mình đã trình bày xong module ngRoute trong AngularJS ứng dụng vào SPA. Các bạn có thể tham khảo thêm:

https://docs.angularjs.org/api/ngRoute/service/$route

https://docs.angularjs.org/api/ngRoute/


All Rights Reserved