Routing là cách để chúng ta di chuyển giữa các trang trong một ứng dụng web. Trong bài viết này, mình sẽ hướng dẫn các bạn cách chúng ta routing trong Angular như thế nào các bạn nhé.
Đầu tiên, mình sẽ tạo một Angular project để làm ví dụ:
Chạy ứng dụng các bạn sẽ thấy kết quả như sau:
Bây giờ, mình sẽ tách nội dung của tập tin app.component.html thành ra 2 trang: một trang home.component.html có nội dung giống như trang app.component.html hiện tại còn trang kia huongdanjava.component.html có nội dung giống phần trên bao gồm chữ “Welcome to app!” và logo Angular, phần dưới thì là dòng chữ “Here is the link to Huong Dan Java” và link tới trang Huong Dan Java của mình. Cụ thể chi tiết nội dung của các tập tin sẽ thay đổi lúc này như sau:
home.component.html:
1 2 3 4 5 6 7 8 9 10 11 12 |
<h2>Here are some links to help you start: </h2> <ul> <li> <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> </li> </ul> |
home.component.ts:
1 2 3 4 5 6 7 8 |
import { Component } from "@angular/core"; @Component({ selector: 'app-body', templateUrl: './home.component.html' }) export class HomeComponent { } |
huongdanjava.component.html:
1 2 3 4 5 6 |
<h2>Here are the link to Huong Dan Java: </h2> <ul> <li> <h2><a target="_blank" rel="noopener" href="https://huongdanjava.com/">Huong Dan Java</a></h2> </li> </ul> |
huongdanjava.component.ts:
1 2 3 4 5 6 7 8 |
import { Component } from "@angular/core"; @Component({ selector: 'app-body', templateUrl: './huongdanjava.component.html' }) export class HuongDanJavaComponent { } |
Lúc này nội dung của tập tin app.component.html sẽ như sau:
1 2 3 4 5 6 7 8 |
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> </div> <app-body></app-body> |
Còn nội dung của class AppComponent cần sửa lại như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HomeComponent } from './home.component'; import { HuongDanJavaComponent } from './huongdanjava.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, HuongDanJavaComponent ], imports: [ BrowserModule ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { } |
Lúc này, nếu các bạn chạy lại ứng dụng, các bạn sẽ không thấy gì cả. Nhưng nếu các bạn click chuột phải, chọn Inspect trong Google Chrome rồi di chuyển đến tab Console các bạn sẽ thấy lỗi như sau:
Đó là do hiện tại chúng ta đang định nghĩa 2 Component có cùng giá trị selector đó các bạn. Không sao cả, các bạn cứ ignore lỗi này trước. Giờ chúng ta sẽ apply routing cho ứng dụng Angular của chúng ta các bạn nhé!
Trong một ứng dụng Angular, module RouterModule sẽ đảm nhận vai trò là đối tượng routing.
Để sử dụng module này, chúng ta cần import nó vào ứng dụng của chúng ta, định nghĩa cách routing: URL nào tương ứng với Component nào, và cuối cùng là export lại nó để ứng dụng của chúng ta có thể sử dụng.
Cụ thể thì mình sẽ tạo mới một tập tin tên là app-routing.module.ts trong thư mục src/app:
rồi định nghĩa mới một module sử dụng RouterModule của Angular như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home.component'; import { HuongDanJavaComponent } from './huongdanjava.component'; const routes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'huongdanjava', component: HuongDanJavaComponent }, ] @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule { } |
Như các bạn thấy ở trên, mình đã sử dụng class Routes để định nghĩa thông tin về các URL tương ứng với các component trong ứng dụng của chúng ta. Path “home” sẽ tương ứng với HomeComponent còn path “huongdanjava” sẽ tương ứng với HuongDanJavaComponent mà mình đã định nghĩa.
Sau khi định nghĩa xong các thông tin URL với component, chúng ta cần truyền các thông tin này vào RouterModule với phương thức static forRoot(). Sau đó thì export RouterModule này ra cho ứng dụng của chúng ta sử dụng.
Sau khi đã định nghĩa xong module AppRoutingModule ở trên, chúng ta cần import nó vào AppModule:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HomeComponent } from './home.component'; import { HuongDanJavaComponent } from './huongdanjava.component'; import { AppRoutingModule } from './app-routing.module'; @NgModule({ declarations: [ AppComponent, HomeComponent, HuongDanJavaComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { } |
rồi thay thế thẻ <app-body> trong tập tin app.component.html bằng thẻ <router-outlet> của Angular để RouterModule có thể biết nội dung của component nào cần được sử dụng khi chúng ta đi đến những trang URL khác nhau.
Nội dung của tập tin app.component.html lúc này sẽ như sau:
1 2 3 4 5 6 7 8 |
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> </div> <router-outlet></router-outlet> |
Lúc này nếu các bạn chạy lại ứng dụng và truy cập đến http://localhost:4200/ thì sẽ thấy kết quả như sau:
Như các bạn thấy, phần nội dung phía dưới lúc này không còn được hiển thị nữa. Chỉ khi nào các bạn request tới http://localhost:4200/home hoặc http://localhost:4200/huongdanjava thì mới thấy. Ví dụ như:
Hoặc:
Nguyên nhân là vì hiện tại chúng ta mới chỉ định nghĩa URL trong RouterModule của Angular cho 2 component là HomeComponent và HuongDanJavaComponent.
Nếu các bạn muốn định nghĩa URL http://localhost:4200/ sử dụng HomeComponent thì có thể định nghĩa thêm trong class Routes như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home.component'; import { HuongDanJavaComponent } from './huongdanjava.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'home', component: HomeComponent }, { path: 'huongdanjava', component: HuongDanJavaComponent }, ] @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule { } |
Khi đó, nếu các bạn request tới URL http://localhost:4200/, các bạn sẽ thấy nội dung của HomeComponent.
Trong trường hợp nếu các bạn muốn khi người dùng request tới một URL không tồn tại trong ứng dụng Angular của các bạn, mặc định trang nội dung của HomeComponent sẽ được trả về thì các bạn có thể cấu hình cho class Routes như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home.component'; import { HuongDanJavaComponent } from './huongdanjava.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'home', component: HomeComponent }, { path: 'huongdanjava', component: HuongDanJavaComponent }, { path: '**', pathMatch: 'full', redirectTo: '/' } ] @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule { } |
Điều cuối cùng mình muốn nói với các bạn trong bài viết này là: để sử dụng các URL mà chúng ta đã định nghĩa trong class Routes, các bạn cần sử dụng directive routerLink của Angular trong thẻ <a> của HTML.
Ví dụ như giờ mình muốn thêm 2 liên kết để điều hướng giữa 2 trang “home” và “huongdanjava” trong trang app.component.html, mình sẽ thêm như sau:
1 2 3 4 5 6 7 8 9 10 |
<!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> </div> <a routerLink="/home">Home</a><p></p> <a routerLink="/huongdanjava">Huong Dan Java</a> <router-outlet></router-outlet> |
Khi đó, các bạn sẽ thấy 2 liên kết xuất hiện khi chúng ta truy cập vào http://localhost:4200:
Nhấp vào những URL trên thì nội dung tương ứng của các trang sẽ được trả về.
Lê Văn Chiến
Chào anh!
Cho em hỏi là phương thức forRoot(), forChild() có chức năng gì thế ạ ?