12/08/2018, 16:34

Tuơng tác giữa các component trong angular 2/4 (p2)

Cũng giống như kỹ thuật local variable nhưng chung ta sẽ khởi tạo biến kiểu của component con thông qua syntax @ViewChild(AppChildComponent) private childCmp: AppChildComponent; Từ biến childCmp chúng ta có thể sử dụng ở bất kì đâu trong component cha với những public resource tử component ...

Cũng giống như kỹ thuật local variable nhưng chung ta sẽ khởi tạo biến kiểu của component con thông qua syntax

@ViewChild(AppChildComponent)
private childCmp: AppChildComponent;

Từ biến childCmp chúng ta có thể sử dụng ở bất kì đâu trong component cha với những public resource tử component con. Parent component

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

@Component({
  selector: 'app-parent',
  template: `
    <h2>Son' foods</h2>
    <button (click)="forceEat()" >Eat</button>
    <app-child ></app-child>
  `
})![](/pictures/picfullsizes/2018/08/12/uza1534043450.png)
export class AppParentComponent {
  @ViewChild(AppChildComponent)
  private childCmp: AppChildComponent;

  forceEat(){
    this.childCmp.eat('rice');
  }
};

Đây là một kỹ thuật mình sử dụng khá nhiều trong việc comunicate giữa các component.

Ngoài những cách được cung cấp ở trên thường sẽ có flow theo hai hướng đó là từ cha -> con và ngược lại từ con -> cha và cha cũng phải include component con trong template của mình. Vì vậy những kĩ thuật trên khá nhiều ngữ cảnh sẽ ko thể apply được.

Hình minh họa bên dưới chỉ rõ 2 cách mà các component làm việc với nhau. Do đó những vấn đề như comunicate từ component ra nhiều component khác (re-render sau khi login, logout, thay đổi ngôn ngữ,...) trong ứng dụng hay tương tác qua lại giữa các component với nhau hoặc bất kể những hoạt động làm việc ở mức global cần tương tác với toàn bộ những component trên ứng dụng angular2 chúng ta nên sử dụng kỹ thuật này.

Ở kỹ thuật đơn giản chỉ là chúng ta cần tạo ra một service trung gian giữa các components để lắng nghe các giá trị truyền đi giữa các component. Trong angular2 chúng ta sẽ sữ dụng RxJs để làm việc này. Ở ví dụ này chúng ta tạo ra 2 component, component cha sẽ lắng nghe mỗi khi component con raise lên 1 message (định nghĩa trong app service và gọi khi component con gọi method say())

childSay(message: string) {
    this.childSaySource.next(message);
}

Ở constructor or ngOnInit của component cha, ta sẽ lắng nghe (hàm subscribe) message được gửi từ appSerive thông qua biến childSaid$$(kiểu Observable) mỗi khi childSaySource gọi method next với bất kì một giá trị nào.

_appService.childSaid$.subscribe(mess => {
      this.sonMess = mess;
});
import { Component } from '@angular/core';
import { AppService } from './app.service';

@Component({
  selector: 'app-root',
  template: `
  <app-parent></app-parent>
  <app-child></app-child>`,
  providers: [AppService]
})
export class AppComponent {
}
**import { Component } from '@angular/core';
import { AppService } from './app.service';

@Component({
  selector: 'app-root',
  template: `
  <app-parent></app-parent>
  <app-child></app-child>`,
  providers: [AppService]
})
export class AppComponent {
}

Một lưu ý nữa là chúng ta khi chung ta subscribe thì cần phải unsubscribe khi những component đã được render xong hoặc nói cách khác là component đó đến lúc việc tạo component đã xong (is destroyed). Đây là bước để app chúng ta tránh khỏi issue về memory-leak. Sẽ không là gì trong một ứng dụng nhỏ như ví dụ này. Nhưng nếu trong một ứng dụng phức tạp nó thì nó là một thảm họa nếu chúng ta không quản lý tốt chúng.

  1. Import từ RxJS
import { Subscription } from 'rxjs/Subscription';
  1. Implement OnDestroy trong Component
import { Component, OnDestroy } from '@angular/core';

@Component({...})

export class AppChildComponent implements OnDestroy {
  1. Gán giá trị cho subscription
constructor(private _appService: AppService) {
      // Lắng nghe lời yêu dấu từ đứa con
      this.subs = _appService.childSaid$.subscribe(mess => {
        this.sonMess = mess;
      });
    }

  1. unsubscribe trong state OnDestroy
ngOnDestroy() {
      this.subs.unsubscribe();
    }
0