Bài viết được dịch từ: toddmotto.com

Đây là hướng dẫn cho những người mới bắt đầu, để giúp bạn dễ dàng làm quen với Angular (v2+), mặc dù đã có nhiều tài nguyên online hướng dẫn cách tạo các component, nhưng bài viết này tồn tại như là một phần của loạt bài hướng dẫn về Angular (v2+).

Mục lục

  • Giới thiệu
  • Tạo một class ES6/TypeScript
  • Sử dụng @Component decorator
  • Tạo một counter component 
    • Định nghĩa component
    • Property binding tới một <input>
    • Các phương thức của component
    • Styling component
  • Đăng ký với @NgModule
  • Plunker
  • Bước tiếp theo

Các bài viết trong loạt bài này

  1. Khởi động ứng dụng Angular đầu tiên của bạn
  2. Tạo Angular component đầu tiên của bạn
  3. Truyền dữ liệu vào các component Angular với @Input
  4. Các event component với EventEmitter và @Output trong Angular

Giới thiệu

Trong bài viết này chúng ta sẽ tạo một component "counter", cái cho phép tăng hoặc giảm các giá trị của một <input> thông qua các button.

Trước khi tạo component đầu tiên của mình, bạn cần biết cách khởi dộng một ứng dụng Angular 2+.

Tạo một class ES6/TypeScript

Tất cả các component trong Angular 2+ đều là các class, và để nói cho Angular 2+ biết chúng là một component, chúng ta sử dụng một decorator đặc biệt, cái chúng ta sẽ học trong phần tiếp theo, bây giờ hãy tạo một class:

class AppComponent {

}

Trong class, chúng ta có thể thêm các thuộc tính, chẳng hạn như một message:

class AppComponent {
  message: string = 'Hello world!';
}

Nếu bạn mới học TypeScript, bạn có thể quen thuộc với hướng tiếp cận này hơn:

class AppComponent {
  constructor() {
    this.message = 'Hello world!';
  }
}

Thực chất, chúng tương tự nhau, nhưng sử dụng TypeScript chúng ta có thể khai báo kiểu cho các thuộc tính, ví dụ message: string, biểu thị rằng nó sẽ có kiểu "string". Tôi cũng cung cấp cho nó một giá trị mặc định "Hello world!".

Tham khảo các khóa học lập trình online, onlab, và thực tập lập trình tại TechMaster

Sử dụng @Component decorator 

Để nói với Angular 2+, class của chúng ta là một component, chúng ta cần import component decorator và sử dụng nó trên class của mình.

Decorator chỉ là các function, bạn có thể đọc hướng dẫn sâu hơn về Angular decorators của tôi khi đã quen với việc sử dụng chúng.

Chúng ta import component decorator từ Angular 2+ core module:

// app.component.ts
import { Component } from '@angular/core';

export class AppComponent {
  message: string = 'Hello world!';
}

Sau khi import Component, chúng ta chỉ cần thêm nó lên phía trên class của mình:

// app.component.ts
import { Component } from '@angular/core';

@Component()
export class AppComponent {
  message: string = 'Hello world!';
}

Có một đề xuất về các decorator tới TC39 (Ecma's Technical Committe 39), hiện tại đang ở Stage-2, mong muốn decorator sẽ trở thành một tính năng chính của JavaScript.

Tiếp theo, chúng ta cần cấu hình 2 thuộc tính là: selectortemplate:

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      {{ message }}
    </div>
  `
})
export class AppComponent {
  message: string = 'Hello world!';
}

Bạn có thể thấy chúng ta sử dụng {{ message }} để liên kết các giá trị của class với các biểu thức tương ứng trong template, ở ví dụ này, nó sẽ render ra "Hello world!" trong trình duyệt.

Bạn đã biết khá rõ cái template làm, nhưng selector để làm gì? Thuộc tính selector tạo ra một component với tên là chuỗi bạn truyền cho nó, để sử dụng như thế này:

<app-root>
  Loading...
</app-root>

Chúng ta đặt "Loading..." (cái bạn có thể tùy biến) bên trong thẻ <app-root>, để hiển thị khi ứng dụng đang loading.

Tạo một counter component 

Hãy tiếp tục, với một ví dụ phức tạp hơn, đó là tạo một CouterComponent chúng ta đã đề cập ở phần giới thiệu.

Định nghĩa component

Bây giờ chúng ta đã hiểu cách tạo ra một component:

// counter.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'counter',
  template: `
    <div class="counter">
      {{ count }}
    </div>
  `
})
export class CounterComponent {
  count: number = 0;
}

Property binding tới một <input>

Để liên kết thuộc tính count tới một <input>, chúng ta cần sử dụng cái gọi là property binding, nó giúp chúng ta liên kết tới một thuộc tính cụ thể trên một DOM element (chúng ta cũng có thể liên kết tới các component, cái chúng ta sẽ học trong bài tiếp theo).

Vậy, thuộc tính nào chúng ta cần liên kết? Đó là thuộc tính value! Bạn có thể đã làm một vài thứ giống như thế này trước đây:

<input type="text" value="Hello">

Đoạn code trên tạo ra một <input> với giá trị mặc định là Hello. Để liên kết một giá trị từ component class tới template, chúng ta cần làm điều này:

@Component({
  selector: 'counter',
  template: `
    <div class="counter">
      <input type="text" [value]="count">
    </div>
  `
})
export class CounterComponent {
  count: number = 0;
}

Dấu ngoặc vuông [ ] ở đây báo hiệu rằng nó là một property binding.

Các phương thức của component

Để tăng và giảm count, chúng ta có thể tạo 2 phương thức trong class:

export class CounterComponent {
  count: number = 0;
  increment() {
    this.count++;
  }
  decrement() {
    this.count--;
  }
}

Đây là các phương thức thao tác trực tiếp với thuộc tính count bên trong component của chúng ta, nó sẽ tự động ánh xạ tới template thông qua property binding mà chúng ta đã làm. Chúng ta cần thêm các button để người dùng tăng và giảm giá trị:

@Component({
  selector: 'counter',
  template: `
    <div class="counter">
      <button>
        Decrement
      </button>
      <input type="text" [value]="count">
      <button>
        Increment
      </button>
    </div>
  `
})
export class CounterComponent {
  // ...
}

Bây giờ, chúng ta cần liên kết một event click tới mỗi button. Điều này được thực hiện thông qua event binding, cái sử dụng dấu ngoặc tròn ( ) thay vì ngoặc vuông [ ]. Bên trong dấu ngoặc tròn, chúng ta cần chỉ định tên của event chúng ta muốn lắng nghe:

@Component({
  selector: 'counter',
  template: `
    <div class="counter">
      <button (click)="decrement()">
        Decrement
      </button>
      <input type="text" [value]="count">
      <button (click)="increment()">
        Increment
      </button>
    </div>
  `
})
export class CounterComponent {
  // ...
}

Styling component

Chúng ta sẽ làm quen với một khái niệm nữa, đó là styling. Để làm điều này, chúng ta cần thêm một thuộc tính styles tới @Component decorator và truyền một mảng các chuỗi:

@Component({
  selector: 'counter',
  styles: [`
    .counter {
      position: relative;
    }
    input {
      border: 0;
      border-radius: 3px;
      height: 30px;
      max-width: 100px;
      text-align: center;
    }
    button {
      outline: 0;
      cursor: pointer;
      height: 30px;
      border: 0;
      border-radius: 3px;
      background: #0088cc;
      color: #fff;
    }
  `],
  template: `
    <div class="counter">
      <button (click)="decrement()">
        Decrement
      </button>
      <input type="text" [value]="count">
      <button (click)="increment()">
        Increment
      </button>
    </div>
  `
})
export class CounterComponent {
  // ...
}

Angular hỗ trợ nhiều khai báo style cho một component nhưng thường thì chúng ta chỉ cần một. Điều này sẽ hữu ích, nếu bạn chia sẻ các style giữa nhiều component, bạn có thể tạo một file style cho các component sử dụng chung. Một lựa chọn khác là styleUrls, nó cho phép chúng ta sử dụng các file style riêng biệt hoặc các file preprocessor chẳng hạn như Sass hoặc Less:

@Component({
  selector: 'counter',
  styleUrls: ['counter.component.scss'],
  template: `
    <div class="counter">
      <button (click)="decrement()">
        Decrement
      </button>
      <input type="text" [value]="count">
      <button (click)="increment()">
        Increment
      </button>
    </div>
  `
})
export class CounterComponent {
  // ...
}

Angular cũng hỗ trợ một external template giúp tách template thành các file riêng biệt. Sau đó, bạn có thể sử dụng templateUrl và trỏ tới file template.

Đăng ký với @NgModule

Bây giờ, sau khi đã tạo ra một component counter, chúng ta phải thêm nó tới @NgModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

// import our new component!
import { CounterComponent } from './counter.component.ts';

import { AppComponent } from './app.component.ts';

@NgModule({
  declarations: [
    AppComponent,
    // register it inside the declarations array
    CounterComponent
  ],
  imports: [
    BrowserModule
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule {}

Đây là một bước quan trọng, cho phép chúng ta sử dụng CounterComponent trong ứng dụng với thẻ <counter>.

Plunker

Mọi thứ chúng ta đã làm đều có sẵn trong một Plunker:

Bước tiếp theo

Bây giờ chúng ta đã học được cách làm những thứ cơ bản, tiếp theo chúng ta sẽ học cách truyền dữ liệu tới các component Angular với @Input.