12/08/2018, 16:15

Angular 2 căn bản - Phần 2: Làm quen với component và service

Ở cuối bài viết trước mình đã đề cập đến component, và ở phần này chúng ta sẽ bắt đầu bằng cách tự build một component theo ý của mình (go) Mình sẽ tạo một component để hiển thị ra một list people. Tuy nhiên, để tiện cho việc chỉnh sửa về sau, mình sẽ tạo một interface là person để export, và trong ...

Ở cuối bài viết trước mình đã đề cập đến component, và ở phần này chúng ta sẽ bắt đầu bằng cách tự build một component theo ý của mình (go) Mình sẽ tạo một component để hiển thị ra một list people. Tuy nhiên, để tiện cho việc chỉnh sửa về sau, mình sẽ tạo một interface là person để export, và trong component mình sẽ import interface đó. Tất nhiên là không phải tạo bằng tay rồi vì Angular CLI đã hỗ trợ sẵn với câu lệnh:

ng generate interface person 
# or 
# ng g i person

mở project và bạn sẽ thấy file src/app/person.ts. Lúc này việc của chúng ta là định nghĩa một person để export

export interface Person {
  name: string;
  weight :number;
  height :number;
}

Và bây giờ mình sẽ tạo component peopleList bằng câu lệnh:

ng generate component --inline-template people-list
# or
# ng g c -it people-list 

Bạn sẽ thấy một folder có tên là people-list được tạo ra trong app. Có thể bạn sẽ thắc mắc --inline-template là gì, mình xin được giải thích luôn: --inline-template là để định nghĩa trực tiếp html cho component trong file component.ts . Mở file people-list.component.ts ta sẽ thấy:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-people-list',
  template: `
    <p>
      people-list Works!
    </p>
  `,
  styleUrls: ['./people-list.component.scss']
})
export class PeopleListComponent implements OnInit {

  // you can ignore these for the time being :)
  constructor() {}
  ngOnInit() {}
}

Một lưu ý nhỏ, bạn có để ý rằng các selector từ đầu đến giờ luôn bắt đầu bởi app-*, đó là bởi Angular CLI quy định như thế. Bạn hoàn toàn có thể thay đổi bằng cách vào file angular-cli.json. Bạn cũng hoàn toàn có thể thay đổi ngay lúc khởi tạo bằng cách sử dụng thuộc tính prefix khi sử dụng câu lệnh ng-new. OK, như vậy là chúng ta đã có một component people-list, việc tiếp theo là tạo một mảng các person để hiển thị, và chúng ta thực hiện bằng tay rất đơn giản thôi, bạn hãy sửa lại file people-list.component.ts như sau:

import { Component, OnInit } from '@angular/core';
import { Person } from '../person';

@Component({
  selector: 'app-people-list',
  template: `
    <p>
      people-list Works!
    </p>
  `,
  styleUrls: ['./people-list.component.scss']
})
export class PeopleListComponent{
  people: Person[] = [
    {name: 'Kobayashi Taihei', height: 177, weight: 65},
    {name: 'Vu Xuan Dung', height: 165, weight: 62},
    {name: 'Tran Ngoc Thang', height: 173, weight: 68},
  ];

  constructor(){}
  ngOnInit(){}
}

và chúng ta sẽ dùng vòng lặp để lấy dữ liệu ra. Angular 2 cung cấp một directive là *ngFor để thực hiện việc này.

  <li *ngFor="let person of people">
    {{person.name}}
  </li>

Và file hoàn chỉnh của chúng ta sẽ như sau:

import { Component, OnInit } from '@angular/core';
import { Person } from '../person';

@Component({
  selector: 'app-people-list',
  template: `
    <ul>
      <li *ngFor="let person of people">
        {{person.name}}
      </li>
    </ul>
  `,
  styleUrls: ['./people-list.component.scss']
})
export class PeopleListComponent implements OnInit {
  people: Person[] = [
    {name: 'Kobayashi Taihei', height: 177, weight: 65},
    {name: 'Vu Xuan Dung', height: 165, weight: 62},
    {name: 'Tran Ngoc Thang', height: 173, weight: 68},
  ];
  constructor() { }

  ngOnInit() {
  }

}

Và đừng quên gọi component này trong app.component.html

<h1>{{title}}</h1>
<app-people-list></app-people-list>

Kết quả thu được như sau: Well, vậy là chúng ta đã đi được một nửa chặng đường rồi. Ở phần còn lại của bài viết chúng ta sẽ tìm hiểu thế nào là service và dependency injection, và nó có vai trò gì trong một ứng dụng Angular 2. Ở phần đầu chúng ta đã tạo một component là people-list-component, trong đó khởi tạo một mảng person. Tuy nhiên, thực sự thì chúng ta không nên quan tâm dữ liệu ở đâu, trong DB hay API..... Đó là lý do tại sao chúng ta nên giao việc truy cập dữ liệu cho service rồi inject service đó vào trong component bằng cách khởi tạo trong constructor của component. Nhiệm vụ của chúng ta bây giờ là tạo một PeopleService để lấy dữ liệu. Nãy giờ chúng ta đề cập đến service khá nhiều, vậy thì service thực ra là cái gì? Service, đúng như tên gọi của nó, là một dịch vụ. Nó đóng gói một số chức năng và cung cấp chúng cho phần còn lại của ứng dụng để sử dụng. Và với Angular 2 thì service được thể hiện dưới dạng một class của ES6. Giải thích đã xong, bắt tay vào làm thôi. Sử dụng câu lệnh sau trong terminal để tạo một service:

ng generate service people
# or
# ng g s people

Mở sublime text lên bạn sẽ thấy một file people.service.ts được tạo ra

import { Injectable } from '@angular/core';

@Injectable()
export class PeopleService {

  constructor() { }

}

Và bây giờ ta sẽ lấy data ở trong service, các bạn nhớ import interface person:

import { Injectable } from '@angular/core';
import { Person } from './person';

@Injectable()
export class PeopleService {

  constructor() { }

  getAll() : Person[] {
    return [
      {name: 'Kobayashi Taihei', height: 177, weight: 65},
      {name: 'Vu Xuan Dung', height: 165, weight: 62},
      {name: 'Tran Ngoc Thang', height: 173, weight: 68},
    ];
  }
}

Và như vậy ta có thể dễ dàng sử dụng service này trong people-list-component bằng cách import nó:

import { PeopleService } from '../people.service';

sau đó gọi đến service này trong constructor:

people: Person[] = [];

constructor(private peopleService: PeopleService) {
  this.people = peopleService.getAll();
}

Có thể bạn sẽ để ý trong phần argument của constructor có một cú pháp khá đặc biệt:

private peopleService: PeopleService

Đó là cú pháp khai báo gọn của TypeScript, nó cũng tương tự như:

  private peopleService: PeopleService;
  people: Person[] = [];

  constructor(peopleService : PeopleService){
    this.peopleService = peopleService
    this.people = this.peopleService.getAll();
  }

Và file people-list.component.ts của chúng ta cuối cùng sẽ được như sau:

import { Component, OnInit } from '@angular/core';
import { Person } from '../person';
import { PeopleService } from "../people.service";

@Component({
  selector: 'app-people-list',
  template: `
    <ul>
      <li *ngFor="let person of people">
        {{person.name}}
      </li>
    </ul>
  `,
  styleUrls: ['./people-list.component.scss']
})
export class PeopleListComponent implements OnInit {
  people: Person[];

  constructor(private peopleService: PeopleService) {
    this.people = peopleService.getAll();
  }

  ngOnInit() {}
}

Tuy nhiên, khi mở lên ứng dụng của chúng ta lại trắng tinh. Hmm, có vẻ như chúng ta đã bỏ qua gì đó.Thử ấn F12 và bùm, một đống error đỏ lòm. Trông thì có vẻ ghê gớm nhưng thực ra ta chỉ cần quan tâm đến dòng đầu tiên mà thôi ERROR Error: No provider for PeopleService! Vậy là do mình quên khai báo service mà nó chưa thể sử dụng được. Có nhiều cách để khai báo nhưng mình sẽ hướng dẫn các bạn cách đơn giản nhất. Mở fileapp.module.ts và import PeopleService vào, sau đó ở chỗ providers ta gọi PeopleService. Nếu các bạn còn nhớ thì ở phần 1 mình đã giải thích về các mục ở file này. Lúc này file module trông như sau:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { PeopleService } from "./people.service";

import { AppComponent } from './app.component';
import { PeopleListComponent } from './people-list/people-list.component';

@NgModule({
  declarations: [
    AppComponent,
    PeopleListComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [PeopleService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Tuy nhiên Angular CLI đã hỗ trợ rất tốt điều này. Khi tạo service bạn chỉ cần sử dụng:

ng generate service people --module app
# in short notation:
# ng g s people -m app

service sẽ tự động được khai báo trong module Done, và lúc này mở ứng dụng lên ta có như sau: Trong phần tiếp theo mình sẽ nói về component thứ 2 và data binding

0