Web Design

Angularjs, Bài 9: Giới thiệu về ngInclude, ngView và Routes

Trong bài cuối cùng về các directives này, chúng ta sẽ tìm hiểu về ngInclude directive, ngView directive và kèm với đó là Routes với AngularJS.

AngularJS

1. ngInclude

Nếu không phải viết một loạt các trang static HTML không liên quan gì nhau thì việc tái sử dụng code HTML là chuyện xảy ra như cơm bữa. Chẳng hạn, như trang EITGUIDE bạn đang nhìn vào đây chẳng hạn, thứ đầu tiên đập vào mắt bạn chính là cái toolbar màu xanh rêu với chữ trắng ngay trên đầu trang đó thôi. Dù ở trang chủ hay vào từng post thì bạn vẫn thấy nó “sừng sững” nơi đó. Với AngularJS, các Google devs cung cấp cho bạn sẵn một directive và chỉ với vài dòng là xong.

Cụ thể, tôi sẽ làm 1 cái toolbar vô cùng đơn giản như bên dưới và lưu nó vào một tập tin HTML. Lưu ý, dù nó là một tập tin HTML nhưng nó không phải là một trang, vì vậy nội dung của nó chỉ là một “trích đoạn” HTML, không có <!DOCTYPE HTML> hay <html>. Nó bắt đầu với thẻ <div> luôn.

Còn đây là trang HTML gốc ban đầu chưa có toolbar, có tên là index.html như bạn có thể dự đoán được. Bên dưới là trang about.html.

Bây giờ tôi sẽ “đính” cái toolbar vào cả 2 trang trên để đi đâu bạn cũng có thể thấy nó. Và, khi đứng từ Trang chính bạn có thể dễ dàng chuyển sang trang Thông tin về chúng tôi, cũng như ngược lại, từ trang Thông tin về chúng tôi lại có thể quay về Trang chính trong vòng một nốt nhạc. Nếu không có ngInclude của AngularJS thì bạn buộc phải cóp pát đoạn trên. Còn nếu đã “thuê” nó vào thì nhanh gọn thôi. Lưu ý là chúng ta đang “nhồi nhét” một trích đoạn HTML trong một trang HTML hoàn chỉnh. Bây giờ tôi “nhồi nhét” toolbar.html vào index.html thì tôi chỉ đơn giản code đúng một dòng giữa <body> và <h1>:

Ngoài việc sử dụng ng-include dưới dạng một HTML tag, ta cũng có thể dùng nó dưới dạng attribute cho một HTML tag và lưu ý là tag này phải có khả năng chứa các tag khác như <div> hay <header>, không thôi nội dung sẽ bị rối. Trước khi xem cách tôi dùng ng-include dưới dạng attr cho about.html, bạn hãy để ý phần src có cả dấu nháy kép và nháy đơn luôn. Khi sử dụng thì bạn hãy theo motive trên mà thôi. Còn ở phần bên dưới này, vì bản thaann ng-include đã là một attr rồi nên bạn không cần attr src nào cả. Cụ thể:

Lưu ý là phần trong dấu nháy đơn của tôi chính là project path của tập tin toolbar.html giống như phần tham số của href của thẻ <a>, chỉ khác là có thêm dấu nháy. Ở đây tôi giả dụ toolbar.html nằm cùng tần với index.htmlabout.html. Nếu bạn có đặt nó trong một thư mục nào thì phải kèm project absolute path trỏ tới nó.Việc sử dụng ngInclude giúp chúng ta tiết kiệm được khá nhiều thời gian cóp pát trên nhiều trang HTML giống nhau, và hơn nữa, khi ta chỉnh sửa file gốc, chẳng hạn toolbar.html ở trên thì mọi trang HTML khác có include nó sẽ chịu ảnh hưởng, do đó nếu có 100 trang HTML cùng include một phân đoạn HTML thì với ngInclude ta không phải cóp pát 100 lần. Và như vậy, tôi xin kết thúc phàn ngInclude ở đây vì nó chỉ có bấy nhiêu lí thuyết đó thôi.

2. ngView và Routes:

Bây giờ bạn nhìn lại phân đoạn toolbar.html bên trên, bạn sẽ thấy nó gồm các thẻ <a> và mỗi khi ta click vào thì nó sẽ giúp ta chuyển trang. Với những trang static HTML thì thoải mái rồi, còn đối với những ứng dụng web, chẳng hạn như trang về ghi chú, thay việc chuyển trang qua lại có khi sẽ làm mất dữ liệu cũng như việc query đi query lại dữ liệu từ server có thể gây quá tải nếu ứng dụng của bạn đang có quy mô tương đối nhỏ, đồng thời thì trình duyệt phải request lại một trang HTML mới, render lại từ đầu dẫn tới việc mất thời gian. Vì vậy, để tối ưu hóa ứng dụng, bạn có thể tiếp tục “thuê mướn” tên ngView này vào với mục đích là chỉ render lại những thứ cần phải render lại, cái nào không cần, vẫn giữ nguyên thì cứ giữ nguyên, dù là bạn chuyển trang đi nữa. Và nó chỉ phát huy tác dụng với AngularJS Routes, còn nếu bạn chỉ sử dụng ngView một mình thì nó không có tác dụng gì cả.

Bây giờ bạn sẽ để ý là sau khi gán cái toolbar.html vào mỗi trang index.htmlabout.html thì chúng chỉ còn khác nhau ở phần nội dung gồm các thẻ <h1> và <p> mà thôi. Vì vậy, với ngView và Routes thì chúng sẽ chỉ render lại những cái đó, còn nguyên cả document thì không cần. Với một trang static nhỏ nhoi như trong ví dụ của chúng ta thì không có gì, nhưng đối với một web app có khối lượng lớn, mấy ngàn dòng HTML với hàm trăm HTML tags khác nhau mà có cái cần render lại, có cái lại không cần, đan xen lẫn nhau thì e là vấn đề sẽ lớn. Do đó, việc “nhờ vả” ngView là điều không chỉ dừng ở mức “nên”, mà thực tế phải ở mức “phải”, “bắt buộc” mới đúng. Quay lại bài, hướng đi mới của chúng ta là gom chúng lại thành đúng một trang duy nhất, về index.html mà thôi, còn about.html sẽ được “hạ cấp” xuống mức view, tức chỉ ngang tầm với toolbar.html mà thôi.

Vậy trang index.html của chúng ta chỉ còn đơn giản như bên dưới. Tôi sẽ thêm 1 tag main với ng-view attr như bên dưới và để đó, chúng ta sẽ quay lại nó sau. Ngoài ra bạn cũng có thể sử dụng ng-view như là một HTML tag cũng được. Ở đây tôi dùng nó như một attr của main. Ngoài ra, tôi cũng cần thêm 1 thẻ script nữa trỏ tới angular-route ngay bên dưới angular:

Như các bạn đang dự đoán, phần nội dung <h1> và các <p> của index.html được dời vào một trang HTML mới có tên là mainpage.html. Nội dung của nó chỉ gồm trích đoạn HTML chứ không phải là một trang HTML hoàn chỉnh:

Và cũng như bạn đang nghĩ, about.html của chúng ta cũng được đơn giản hóa như sau:

Như vậy ta đã hoàn thành xong các bước chuẩn bị cho HTML. Phần điều hướng thì sẽ được code trong Javascript. Tôi sẽ đưa ra code trước và giải thích sau:

Thứ nhất, trong array làm param thứ hai của angular.module, bạn sẽ phải “thuê mướn” một tên “ngRoute” vào. Bạn phải khai báo nó ở đó thì với dùng được tên $routeProvider do nó cung cấp, bằng không thì AngularJS sẽ mắt tròn mắt dẹt nhìn bạn mà không hiểu tên $routeProvider là gì vì trong tập tin angular.min.js không có cung cấp phần Routing này. Do đó bạn phải thêm tên angular-route.min.js vào, và khai báo nó trong array param thứ hai của angular.module. Sau này cũng vậy, nếu bạn bắt buộc phải “lôi kéo” thêm bất kì một dependency khác của angularjs vốn không có trong tập tin CDN gốc, bạn sẽ phải bỏ đúng object bạn cần từ tập tin angular CDN vừa thêm mới vào trong array kia, chẳng hạn ngRoute được cung cấp trong gói angular-route.

Thứ hai, $routeProvider là một member trong ngRoute có tác dụng điều hướng, nó sẽ override các điều hướng liên quan tới angularjs trong ứng dụng của bạn thay vì để trình duyệt trực tiếp làm. Mỗi .when gồm 2 param, cái đầu tiên là phần đuôi url trên thanh địa chỉ của bạn, còn phần sau là một object trong đó có chứa một property là templateUrl trỏ tới tập tin phân đoạn HTML mà bạn muốn liên kết và sẽ được nhúng trong thẻ <main> của index.html. Điều này có nghĩa là khi url có đuôi là “/main” thì phần nội dung của <main> sẽ chứa nội dung của “mainpage.html”. Tương tự cho “/about”. Còn .otherwise, đúng như tên gọi của nó, là nếu đuôi url không được định nghĩa trong .when thì nó sẽ điều hướng tới đuôi đó. Ở đây tôi cho về “/main” nhưng nếu muốn, bạn có thể cho về trang 404NotFound của bạn. Cũng xin lưu ý là hàm config gọi từ myApp sẽ được đặt trước controller để định hướng trước. Nếu bạn đặt sau thì chúng không hoạt động được vì bạn định nghĩa controller trước trong khi trên trang HTML đã render nó ra đâu? Và angularjs sẽ mắt dẹt mắt tròn hỏi lại bạn là ng-controller kia nằm ở chỗ nào?

Lưu ý là kể từ bây giờ, giữa phần địa chỉ chính của trang web và đuôi url trỏ tới route sẽ có dấu #, chẳng hạn như http://eitguide.net/#/main hay http://127.0.0.1:3000/#/about. Và bây giờ bạn có để ý là chúng ta đã thay đổi đuôi url không? Vì vậy ta cũng cần đổi nội dung của toolbar.html một chút:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.