EventEmitterHTTPAsync Router Reactive Forms References

Angular uses observables as an interface to handle various common asynchronous operations. Such as:

  • EventEmitterThe class is derived fromObservable.
  • The HTTP module uses observables to handle AJAX requests and responses.
  • The router and the form module use observables to listen for responses to user input events.

EventEmitter

Angular provides an EventEmitter class that sends values through the component’s @Output() decorator. EventEmitter extends the RxJS Subject and adds an emit() method so that it can send arbitrary values. When you call emit(), you pass the sent value to the next() method of the subscribed observer. Let’s look at the class definition:

export declare class EventEmitter<T extends anyextends Subject<T{

    / * *

     * Creates an instance of this class that can

     * deliver events synchronously or asynchronously.

     *

     * @param isAsync When true, deliver events asynchronously.

     *

* /


    constructor(isAsync? : boolean);

/ * *

* Emits an event containing the given value.

* /

emit(value? : T): void;

/ * *

* Registers handlers for events emitted by this instance.

* /

subscribe(generatorOrNext? : any, error? : any, complete? : any): Subscription;

}

Copy the code

EventEmitter, along with the @Output directive, uses handlers in components that send custom events synchronously or asynchronously and register these events by subscribes to instances.

Let’s demonstrate an example of passing data between components.

Subcomponents zippy.com ponent. Ts

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





@Component({

  selector'app-zippy'.

  templateUrl'

    <div class="zippy">

<div (click)="toggle()"> Click on the text </div>

      <div [hidden]="visible">

        <ng-content></ng-content>

      </div>

    </div>

  '


})

export class ZippyComponent implements OnInit {

  visible = true;

  // tslint:disable-next-line: no-output-native

  @Output() open = new EventEmitter<any>();

  // tslint:disable-next-line: no-output-native

  @Output() close = new EventEmitter<any>();



  constructor() {}



  ngOnInit(): void {

  }



  toggle() {

    this.visible = !this.visible;

    if (this.visible) {

      this.close.emit('off');

    } else {

      this.open.emit('open');

      this.open.subscribe((data) = > {

        console.log('open subscribe:' + data);

      });

    }

  }

}

Copy the code

The parent component home4.com ponent. Ts

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



@Component({

  selector'app-home4'.

  templateUrl'

<app-zippy (open)="onOpen($event)" (close)="onClose($event)"> </app-zippy>

  '


})

export class Home4Component implements OnInit {



  constructor() {}



  ngOnInit(): void {

  }



  onOpen(e) {

    console.log(e);

  }



  onClose(e) {

    console.log(e);

  }

}

Copy the code

Run the project, click on the text content on the page, and observe the console output. As shown below:

Angular Development Practice # 8: Use ng-Content for component content projection

HTTP

Angular’s HttpClient returns an observable from an HTTP method call. For example, http.get(‘/API ‘) returns an observable. It has a number of advantages over the Promise based HTTP API:

  • Observables do not modify the server’s response (and concatenation of promises).then()Call the same). Instead, you can use a series of operators to convert these values on demand.
  • HTTP requests are allowed throughunsubscribe()Method to cancel.
  • Requests can be configured to get changes in progress events.
  • Failed requests are easy to retry.

As for the section on data interaction, there were test cases for BOTH GET and POST requests. Looking back at what was a bit confusing at the time, it becomes clear now.

Async pipeline

The AsyncPipe subscribes to an observable or promise and returns the last value it emitted. When a new value is emitted, the pipeline marks the component as needing to be checked for change.

The following example binds the Time observable to the component’s view. The observable constantly updates the component’s view with the current time.

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

import { Observable } from 'rxjs';



@Component({

  selector'app-asyncpipe'.

  templateUrl'

    <div><code>observable|async</code>:

      Time: {{ time | async }}</div>



  '


})

export class AsyncpipeComponent implements OnInit {



  time: Observable<any>;

  constructor() {}



  ngOnInit(): void {

    this.time = new Observable(observer= > {

      setInterval((a)= > {

        observer.next(new Date().toString());

      }, 1000);

    });

  }



}

Copy the code

This is equivalent to subscribing to time and receiving values from next in real time. Observable, as defined above, prints time per second. The page receives values of type Observable.

Page test effect:

observable|async: Time: Tue Apr 14 2020 09:39:46 GMT+0800(China Standard Time)

Copy the code

If you want to receive an object, this value is required.

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

import { Observable } from 'rxjs';



@Component({

  selector'app-asyncpipe'.

  templateUrl'

    <ng-container *ngIf="time2 |async as tim">

      <div>

        {{tim.date}}---{{tim.time}}

      </div>

    </ng-container>

  '


})

export class AsyncpipeComponent implements OnInit {



  time2: Observable<any>;

  constructor() {}



  ngOnInit(): void {

      this.time2 = new Observable(observer= > {

      setInterval((a)= > {

        const dd = new Date(a);

        observer.next({ date: dd.toString(), time: dd.toTimeString() });

      }, 1000);

    });

  }



}

Copy the code

Page test results:

Tue Apr 14 2020 0949:: 38 GMT+0800 (China Standard Time)- 0949:: 38 GMT+0800 (China Standard Time)

Copy the code

Router (router)

Router.events provides its events in the form of observables. You can use the filter() operator in RxJS to find events of interest and subscribe to them to make decisions based on the sequence of events generated during browsing. Examples are as follows:

import { Router, NavigationStart } from '@angular/router';

import { filter } from 'rxjs/operators';



@Component({

  selector'app-routable'.

  templateUrl'./routable.component.html'.

  styleUrls: ['./routable.component.css']

})

export class Routable1Component implements OnInit {



  navStart: Observable<NavigationStart>;



  constructor(private router: Router) {

    // Create a new Observable that publishes only the NavigationStart event

    this.navStart = router.events.pipe(

      filter(evt= > evt instanceof NavigationStart)

    ) as Observable<NavigationStart>;

  }



  ngOnInit() {

    this.navStart.subscribe(evt= > console.log('Navigation Started! '));

  }

}

Copy the code

ActivatedRoute is an injectable router service that uses observables to obtain information about routing paths and routing parameters. For example, the Activatedroute. url contains an observable that reports routing paths. We only need to modify the product-detail.component.ts file in conjunction with the JS jump of dynamic routing in Angular Basics (2) :

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

import {ActivatedRoute} from '@angular/router';



@Component({

  selector'app-product-detail'.

  templateUrl'./product-detail.component.html'.

  styleUrls: ['./product-detail.component.css']

})

export class ProductDetailComponent implements OnInit {



  constructor(public router: ActivatedRoute) {

  }



  ngOnInit(): void {

    this.router.url.subscribe(url= > console.log('The URL changed to: ' + url));

  }



}

Copy the code

Page test results are:

Such as ActivatedRoute again. The observed object queryParams contains routing jump pass parameters. Modify the news.component.ts file based on the case of my previous article:

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

import {ActivatedRoute} from '@angular/router';



@Component({

  selector'app-news'.

  templateUrl'./news.component.html'.

  styleUrls: ['./news.component.css']

})

export class NewsComponent implements OnInit {



  nums: any[] = [];



  constructor(public router: ActivatedRoute) {

    this.router.queryParams.subscribe((data) = > {

      console.log(data);

    });

  }



  ngOnInit(): void {



  }



}

Copy the code

Page test results are:

Reactive Forms

Reactive forms have properties that use observables to listen for values of form controls. The valueChanges and statusChanges properties of FormControl contain observables that emit change events. Subscribing to observable form control properties is one way to trigger application logic in a component class. Such as:

import { FormGroup } from '@angular/forms';



@Component({

  selector'my-component'.

  template'MyComponent Template'

})

export class MyComponent implements OnInit {

  nameChangeLog: string[] = [];

  heroForm: FormGroup;



  ngOnInit() {

    this.logNameChange();

  }

  logNameChange() {

    const nameControl = this.heroForm.get('name');

    nameControl.valueChanges.forEach(

      (value: string) = > this.nameChangeLog.push(value)

    );

  }

}

Copy the code

reference

angular Observable