Make writing a habit together! This is the 8th day of my participation in the “Gold Digging Day New Plan Β· April More Text Challenge”. Click here for more details
Last time, we talked about Angular with NG-Zorro rapid development. Front-end development, to a large extent, is componentized development, which is inseparable from the communication between components. What about communication between Angular components in Angular development?
Vue and React are similar
This article is pure text, more boring. Because the console print things are relatively weak, so it does not fit the graph, HMM ~ hope readers follow the instructions to walk through the code easier to absorb ~
1. The parent component passes values to the child components via properties
You define a property and pass the value to the child component through the introduction of the component. Show you the CODE.
<! -- parent.component.html -->
<app-child [parentProp] ="'My kid.'"></app-child>
Copy the code
Calls the child component in the parent component, naming a parentProp property here.
// child.component.ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-child'.templateUrl: './child.component.html'.styleUrls: ['./child.component.scss']})export class ChildComponent implements OnInit {
// Enter the decorator
@Input() parentProp! :string;
constructor() { }
ngOnInit(): void{}}Copy the code
The child component takes the variable parentProp passed in by the parent and fills it back into the page.
<! -- child.component.html -->
<h1>Hello! {{ parentProp }}</h1>
Copy the code
2. Child components transmit information to their parents through Emitter events
Passing data from the child to the parent via new EventEmitter().
// child.component.ts
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child'.templateUrl: './child.component.html'.styleUrls: ['./child.component.scss']})export class ChildComponent implements OnInit {
// Output decorator
@Output(a)private childSayHi = new EventEmitter()
constructor() { }
ngOnInit(): void {
this.childSayHi.emit('My parents'); }}Copy the code
Emit is used to notify the parent component, which listens for events.
// parent.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-communicate'.templateUrl: './communicate.component.html'.styleUrls: ['./communicate.component.scss']})export class CommunicateComponent implements OnInit {
public msg:string = ' '
constructor() { }
ngOnInit(): void{}fromChild(data: string) {
// Use asynchrony here
setTimeout(() = > {
this.msg = data
}, 50)}}Copy the code
In the parent component, we use the setTimeout asynchronous operation after listening on the data from the Child component. This is because we emit after initialization in the child component, where the asynchronous operation is to prevent a Race Condition Race error.
We also need to add the fromChild method to the component as follows:
<! -- parent.component.html -->
<h1>Hello! {{ msg }}</h1>
<app-child (childSayHi) ="fromChild($event)"></app-child>
Copy the code
3. By reference, the parent component obtains the properties and methods of the child component
We retrieve child component objects by manipulating references and then access their properties and methods.
Let’s first set up the child component’s demo:
// child.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-child'.templateUrl: './child.component.html'.styleUrls: ['./child.component.scss']})export class ChildComponent implements OnInit {
// Attributes of the child component
public childMsg:string = 'Prop: message from child'
constructor() { }
ngOnInit(): void{}// Subcomponent methods
public childSayHi(): void {
console.log('Method: I am your child.')}}Copy the code
We set the child reference identifier #childComponent on the parent component:
<! -- parent.component.html -->
<app-child #childComponent></app-child>
Copy the code
Then call it on the javascript file:
import { Component, OnInit, ViewChild } from '@angular/core';
import { ChildComponent } from './components/child/child.component';
@Component({
selector: 'app-communicate'.templateUrl: './communicate.component.html'.styleUrls: ['./communicate.component.scss']})export class CommunicateComponent implements OnInit {
@ViewChild('childComponent') childComponent! : ChildComponent;constructor() { }
ngOnInit(): void {
this.getChildPropAndMethod()
}
getChildPropAndMethod(): void {
setTimeout(() = > {
console.log(this.childComponent.childMsg); // Prop: message from child
this.childComponent.childSayHi(); // Method: I am your child.
}, 50)}}Copy the code
One limitation of this method π« is that the modifier of the child property must be public, and an error will be reported when protected or private. You can try changing the modifier of a child component. The reasons for the error are as follows:
type | Using range |
---|---|
public | Allows to be called in and out of tired areas, the widest range |
protected | Can be used within a class or in an inherited subclass, with moderate scope |
private | Allows use within a class with the narrowest scope |
4. Use service to change
Let’s demonstrate this with RXJS.
RXJS is a library for responsive programming using Observables, which makes it easier to write asynchronous or callback-based code.
There will be an article documenting RXJS later, so stay tuned
Let’s start by creating a service called parent-and-Child.
// parent-and-child.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; // The BehaviorSubject is real-time and gets the latest values
@Injectable({
providedIn: 'root'
})
export class ParentAndChildService {
private subject$: BehaviorSubject<any> = new BehaviorSubject(null)
constructor(){}// Make it observable
getMessage(): Observable<any> {
return this.subject$.asObservable()
}
setMessage(msg: string) {
this.subject$.next(msg); }}Copy the code
We then reference the parent and child components, whose information is shared.
// parent.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
// Import services
import { ParentAndChildService } from 'src/app/services/parent-and-child.service';
import { Subject } from 'rxjs'
import { takeUntil } from 'rxjs/operators'
@Component({
selector: 'app-communicate'.templateUrl: './communicate.component.html'.styleUrls: ['./communicate.component.scss']})export class CommunicateComponent implements OnInit.OnDestroy {
unsubscribe$: Subject<boolean> = new Subject();
constructor(
private readonly parentAndChildService: ParentAndChildService
) { }
ngOnInit(): void {
this.parentAndChildService.getMessage()
.pipe(
takeUntil(this.unsubscribe$)
)
.subscribe({
next: (msg: any) = > {
console.log('Parent: ' + msg);
// εθΏζ₯ζε° Parent: null
// Prints Parent: Jimmy after one second}});setTimeout(() = > {
this.parentAndChildService.setMessage('Jimmy');
}, 1000)}ngOnDestroy() {
// Unsubscribe
this.unsubscribe$.next(true);
this.unsubscribe$.complete(); }}Copy the code
import { Component, OnInit } from '@angular/core';
import { ParentAndChildService } from 'src/app/services/parent-and-child.service';
@Component({
selector: 'app-child'.templateUrl: './child.component.html'.styleUrls: ['./child.component.scss']})export class ChildComponent implements OnInit {
constructor(
private parentAndChildService: ParentAndChildService
){}// For better understanding, I have removed the parent component's Subject here
ngOnInit(): void {
this.parentAndChildService.getMessage()
.subscribe({
next: (msg: any) = > {
console.log('Child: '+msg);
// εθΏζ₯ζε° Child: null
// Print Child: Jimmy after one second}}}})Copy the code
In the parent component, we change the value after a second. So in the parent component, the initial value of MSG, NULL, is printed as soon as it comes in, and then a second later, the changed value Jimmy is printed. Similarly, if you print information about a service in a child component, the parent component prints the relevant value as well as the child component.
γ the γ β