Search This Blog

Sunday, July 30, 2017

ASP.NET MVC với AngularJS 2. Bài 2: Tìm hiểu về cấu trúc AngularJS 2, Component và Module.


1. Tạo project ASP.NET MVC sử dụng AngularJS 2.
Tạo mới một project ASP.NET MVC có tên AngularJS4_2 và cấu hình để project của chúng ta sử dụng AngularJS 2 tương tự như bài đầu tiên.
Bài viết đầu tiên ở đây http://kienchu.blogspot.com/2017/07/aspnet-mvc-voi-angularjs-2-version-4.html

Sau đó tạo mới 1 folder app. Chúng ta có project ASP.NET MVC với AngularJS 2 như hình bên dưới.

Click phải lên file package.json, chọn Restore Packages để tải về các package cần thiết cho AngularJS 2.


2. Tìm hiểu về Component và Module trong AngularJS 2.
AngularJS 2 là một binding javascript framework, mục đích chính là để binding data giữa các object trong Javascript và các HTML elements, có thể nói nó sử dụng mô hình MVVM (Model - View - ViewModel) hay MVW (Model - View - Whatever). Hình bên dưới mô tả cái nhìn cơ bản về AngularJS 2.
Vì mục tiêu chính của AngularJS 2 là binding code, data giữa ModelView, và để làm việc này trong AngularJS 2 sử dụng khái niệm Component, trong các dự án lớn hơn thì số lượng Component sẽ rất nhiều, nên để quản lý, nhóm các Component lại thì AngularJS 2 sử dụng khái niệm Module. Hình bên dưới thể hiện mối quan hệ quan hệ giữa các thành phần trong AngularJS 2.
- Component: chứa các binding logic để bind code, data giữa Model và View.
- Module: nhóm, quản lý các Component.
OK!. Để dễ hình dung, Kiên sẽ tạo ví dụ minh họa.
Trong folder app, tạo mới 4 folder:
- Model:chứa các Model business TypeScript class.
- Component: chứa các Component dùng để binding data giữa View và Model.
- Module: chứa các Module dùng để nhóm, quản lý các Component.
- View: chứa các HTML template dùng để hiển thị giao diện người dùng (UI).


Trong thư mục Model, tạo mới một file TypeScript và đặt tên là StudentModel.ts.

Bên trong file StudentModel.ts, cập nhật code như bên dưới, đơn giản là khai báo 3 property Id, FirstName, LastName thể hiện các thuộc tính cần có của một Student.
Điểm chú ý là chúng ta cần sử dụng keyword "export" để cho các Component khác có thể nhìn thấy và sử dụng được StudentModel này. Để dễ hình dung, cứ tưởng tượng "export" giống như "public" trong OOP.
 export class StudentModel {  
   Id: string = "";  
   FirstName: string = "";  
   LastName: string = "";  
 }  
Trong thư mục Component, tạo mới một file TypeScript và đặt tên là StudentComponent.ts.
Trong StudentComponent.ts, chúng ta cần import package "@angular/core" và "StudentModel" đã tạo ra trước đó.
 import { Component } from "@angular/core";  
 import { StudentModel } from "../Model/StudentModel";  
Ở trên chúng ta nói Component dùng để binding giữa Model và View, chính vì vậy:
- B1: Chúng ta cần chỉ ra StudentComponent của chúng ta liên kết với View nào. Trong AngularJS 2 có khái niệm Component Metadata Attribute phục vụ cho việc này. Một Component Metadata Attribute khai báo bắt đầu bằng "@Component" sử dụng các Metadata như "selector", "template", "templateUrl"...để xác định View.
 @Component({  
   selector: "app",  
   templateUrl:"../../View/StudentTemplate.html"  
 })  
Đoạn khai báo binding code này mang ý nghĩa: hiển thị nội dung trong file HTML template theo đường dẫn "../../View/StudentTemplate.html" vào đoạn placeholder tag <app></app> được khai báo nơi nào đó trên View.
- B2: Khai báo Model để View có thể nhìn thấy và sử dụng: bằng cách khởi tạo StudentComponent, bên trong khai báo một Model có tên là CurrentStudent.
 export class StudentComponent {  
   CurrentStudent: StudentModel = new StudentModel();  
 }  
Chú ý thêm keyword "export" để các Module có thể nhìn thấy và sử dụng StudentComponent này.
Hình bên dưới là nội dung của StudentComponent.ts.

Tiếp theo trong thư mục View, tạo mới một file HTML template và đặt tên là StudentTemplate.html. Nội dung bên trong đơn thuần là code HTML và cơ chế binding data.
 <div class="container">  
   <div class="row>">  
     <div class="col-sm-6">  
       Student Id:<br />  
       <input type="text" [(ngModel)]="CurrentStudent.Id" /><br />  
       First Name:<br />  
       <input type="text" [(ngModel)]="CurrentStudent.FirstName" /><br />  
       Last Name:<br />  
       <input type="text" [(ngModel)]="CurrentStudent.LastName" /><br />  
     </div>  
     <div class="col-sm-6">  
       Output:<br />  
       {{CurrentStudent.Id}}<br />  
       {{CurrentStudent.FirstName}}<br />  
       {{CurrentStudent.LastName}}<br />  
     </div>  
   </div>  
 </div>  

Nói về binding data, trong StudentComponent đã khởi tạo một Model có tên CurrentStudent, chính vì vậy, trong View đã có thể truy xuất được Model của chúng ta.
AngularJS 2 sử dụng khái niệm gọi là Directives để bind data. Ví dụ [(ngModel)]="CurrentStudent.Id" giúp chúng ta binding data trong property CurrentStudent.Id đến View và ngược lại, tức là hai chiều (2 ways), tức là nếu Model có giá trị, nó sẽ hiển thị lên View, và trên View nếu chúng ta thay đổi giá trị, nó cũng sẽ được cập nhật lại cho Model. Chú ý là CurrentStudent chính là Model mà chúng ta đã khởi tạo trong StudentComponent.
Chi tiết hơn về cơ chế binding:
- (...): gửi dữ liệu từ View -> Model (1 way).
- [...]: gửi dữ liệu từ Model -> View (1 way).
- [(...)]: gửi dữ liệu từ View -> ModelModel -> View (2 ways).
Ngoài ra chúng ta có thể sử dụng {{...}} chỉ để hiển thị dữ liệu từ Model -> View.Ví dụ: {{CurrentStudent.Id}}.

Tiếp theo chúng ta cần tạo Module để nhóm các Component cũng như các Service khác. Trong thư mục Module, tạo mới một file TypeScript và đặt tên là StudentModule.ts.
Trong StudentModule.ts, cần import các package cần thiết như BrowserModule (có các component để viết các điều kiện If, For... trên View), FormsModule (cung cấp các Directives như NgModel, expression..), NgModule (giúp chúng ta định nghĩa NgModule bên trong StudentModule), đồng thời import StudentComponent mà chúng ta đã tạo ra ở bước trên.
 import { BrowserModule } from "@angular/platform-browser";  
 import { FormsModule } from "@angular/forms";  
 import { NgModule } from "@angular/core";  
 import { StudentComponent } from "../Component/StudentComponent";  
NgModule gồm có 3 thuộc tính:
- Imports: định nghĩa các module nếu chúng đang được sử dụng đâu đó trong các component của chúng ta.
- Declarations: định nghĩa các component của module này. Đối với StudentModule thì hiện tại chỉ có 1 StudentComponent.
- Bootstrap: định nghĩa Component đầu tiên sẽ chạy. Ví dụ chúng ta có nhiều Component như HomeComponent, AccountComponent...thì HomeComponent rất có thể sẽ được định nghĩa trong Bootstrap.
Bên dưới là đoạn khai báo NgModule của StudentModule.ts
 @NgModule({  
   imports: [BrowserModule, FormsModule],  
   declarations: [StudentComponent],  
   bootstrap: [StudentComponent]  
 })  
Cuối cùng là chúng ta khởi tạo và export StudentModule.
 export class StudentModule {}  
Full code của StudentModule.ts.

OK!. Vậy là chúng ta đã tạo Model, View, Component (1 hoặc nhiều) và Component này được nhúng trong Module. Và trong 1 project chúng ta vẫn có thể có nhiều Module. Nhưng chúng ta vẫn cần có một Module dùng để chạy lần đầu tiên (startup module), đó có thể là file main.ts mà chúng ta đã tạo trong bài 1.
Xem lại bài 1 ở đây: http://kienchu.blogspot.com/2017/07/aspnet-mvc-voi-angularjs-2-version-4.html

Chúng ta có thể copy lại file này hoặc tại thư mục gốc, tạo mới một file TypeScript và đặt tên là main.ts có nội dung như bên dưới
 import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";  
 import { StudentModule } from "./app/Module/StudentModule";  
 platformBrowserDynamic().bootstrapModule(StudentModule);  
Chúng ta định nghĩa là Module nào sẽ được chạy đầu tiên bằng cách sử dụng
 platformBrowserDynamic().bootstrapModule(StudentModule);  
Cuối cùng build project và kiểm tra các file .js.js.map đã được sanh ra chưa.

3. Chạy thử và test.
Mở file Views\Shared\_Layout.cshtml, nhúng các file js cần thiết trong tag <head></head>
 <head>  
   <meta charset="utf-8" />  
   <meta name="viewport" content="width=device-width, initial-scale=1.0">  
   <title>@ViewBag.Title - My ASP.NET Application</title>  
   <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />  
   <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />  
   <script src="~/Scripts/modernizr-2.6.2.js"></script>  

   <script src="~/node_modules/core-js/client/shim.min.js"></script>  
   <script src="~/node_modules/zone.js/dist/zone.js"></script>  
   <script src="~/node_modules/systemjs/dist/system.src.js"></script>  
   <script src="~/node_modules/reflect-metadata/Reflect.js"></script>  
   <script src="~/systemjs.config.js"></script>  
   <script>  
    System.import('main.js').catch(function(err){ console.error(err); });  
   </script>  
 </head>  
- shim.min.js: đảm bảo ES6 javascript có thể chạy trên các browser cũ.
- zone.js: đảm bảo các task Async hoạt động trong 1 context.
- reflect.js: apply meda-data trong các javascript class như @NgModule, @NgComponent
- system.src.js: support để load các file js sử dụng các module như commonjs, AMD, UMD.

Mở file Views\Home\Index.cshtml, bổ sung placeholder tag <app></app> đã được khai báo selector trong file StudentComponent.ts.

Cuối cùng build và chạy thử (F5).
Mỗi khi chúng ta nhập giá trị cho các fied Student Id, First Name, Last Name, thì trong phần Output sẽ hiển thị giá trị ngay lập tức.


OK!. Kết thúc Bài 2: Tìm hiểu cấu trúc AngularJS 2, Componnent, Module trong loạt bài ASP.NET MVC và AngularJS2. Các bài viết tiếp theo sẽ được cập nhật trong thời gian tới.

Source code tham khảo Ở ĐÂY.

Bài 1 - Cài đặt và cấu hình AngularJS 2 trong ASP.NET MVC

------
Share to be shared
------

No comments:

Post a Comment