En este artículo, aprenderemos cómo Observable admite el intercambio de datos entre editores y suscriptores en una aplicación angular. Se hace referencia a un Observable como una mejor técnica para el manejo de eventos, la programación asíncrona y el manejo de múltiples valores en comparación con técnicas como las promesas.
-
Observable: representa un flujo o fuente de datos que pueden llegar con el tiempo. Pero lo observable no tiene sentido sin un Suscriptor.
-
Suscriptor: Simplemente, es un fragmento de código que vigila el Observable y sus datos. Obtiene los datos y los hace útiles para el componente.
Conocimiento previo:
- Angular v6.2.9 o superior y RxJs v6.4.0 o superior
- Node v10.15.3 o superior y NPM v6.4.1 o superior
(Nota: RxJs se instala automáticamente con Angular, de manera similar, NPM se instala automáticamente con Node)
Debes haber entendido el concepto básico de Observable y Subscribe en Angular. De lo contrario, siga el artículo Cómo implementar Observable-Subscribe en la aplicación Angular .
Estructura del proyecto: se verá así
La forma más común y sencilla de crear Observable: la forma más común y sencilla de crear Observable es mediante los métodos proporcionados por la biblioteca RxJs. Es una biblioteca de terceros que se instala automáticamente cuando crea un nuevo proyecto angular. Uno de esos métodos es fromEvent . Discutiremos otros métodos como Interval y Timer más adelante.
FromEvent: FromEvent es un método proporcionado por RxJs para crear Observable. Lo mejor es que podemos crear Observable a partir de eventos DOM directamente. Por eventos DOM, significa evento de clic, eventos de activación de teclas, eventos de desplazamiento, etc. Es un simple clic del mouse, podemos crear un flujo de datos, es decir, un Observable. FromEvent nos ayudará con eso.
Sintaxis:
fromEvent(target,eventName) .subscribe((res)=>{console.log(res)})
Hablemos de los dos parámetros.
target : puede ser cualquier DOM EventTarget, como un botón, un botón de radio, un control deslizante, etc. Sea cual sea el DOM EventTarget que estemos usando, debe tener métodos para registrar/desregistrar el controlador de eventos. Los elementos que discutimos anteriormente son mecanismos incorporados. No tenemos que escribir código para eso.
eventName : Es el tipo de evento que queremos escuchar.
Ejemplo : clic, mousedown, mouseup, clic, dblclick, mousemove, mouseover, mousewheel, mouseout, touchstart, touchmove, touchend, touchcancel, keydown, keypress, keyup, etc.
Enfoque: crearemos un botón simple «Agregar libro» en la interfaz de usuario y con cada clic en este botón, crearemos un flujo de datos. Para mantenerlo simple, nuestro flujo de datos contendrá solo una string codificada, es decir, «Libro». Con cada clic, seguiremos generando el Libro 1, el Libro 2, el Libro 3, y así sucesivamente. Para mostrar este flujo en la interfaz de usuario, crearemos un <ul> vacío y seguiremos agregando cada libro como un elemento de lista, es decir, <li> en <ul> en tiempo de ejecución.
Preparación: para crear un observable a partir de cualquier evento activado por un elemento DOM, primero debemos obtener una referencia a ese elemento DOM. Esto se puede hacer usando ViewChild y ElementRef. Entonces, el código para esto se puede escribir como:
- HTML:
<button #addBtn>Add</button>
- TypeScript:
@ViewChild(‘addBtn’, {static: true}) addBtn: ElementRef;
Aquí this.addBtn.nativeElement devuelve el elemento DOM nativo. Este será nuestro objetivo (o EventTarget para ser precisos), que es el primer argumento para el método fromEvent. El segundo argumento es ‘clic’ porque estamos usando un clic de botón. Entonces, el código se convierte en:
JavaScript:
fromEvent(this.addBtn.nativeElement, 'click') .subscribe((res)=>{console.log(res)}
¡Surge una pequeña pregunta! ¿Dónde ponemos esta línea de código?
Bueno, el mejor lugar es ngAfterViewInit. Esto se debe a que ViewChild no inicializará el elemento addBtn hasta que se complete ngOnInit. Por lo tanto, pondremos este código dentro de ngAfterViewInit porque, en cuanto a prioridad, ngOnInit es el primer método que se ejecutará cuando se cargue el componente.
JavaScript:
ngAfterViewInit() { fromEvent(this.addBtn.nativeElement, 'click') .subscribe((res) => { console.log(res); }) }
Si hacemos clic en el botón, obtendremos esto en la consola:
Comencemos por convertirlo en un código de trabajo.
-
Paso 1: Crear un nuevo proyecto Angular
ng new observable-app
-
Paso 2: Cree un componente llamado FromEventComponent
ng g c from-event
Deben crearse 4 archivos nuevos y app.module.ts debe actualizarse;
-
Paso 3: Crear un servicio PrintService
ng g s print-service
Podemos hacer esto sin servicio pero para hacer que nuestro código sea más dinámico y significativo. Usemos un servicio. Esto se está haciendo. Ahora hagamos los cambios necesarios para que funcione.
from-event.component.html
<!-- To display the data/stream on UI we will keep on adding each stream as a list item in ul below --> <ul id="elementContainer"></ul> <!-- Button which will create a stream --> <button #addBtn>Add Book</button>
print-service.service.ts
printStream(containerName, stream) { let element = document.createElement('li'); element.innerText = stream; document.getElementById(containerName).appendChild(element); }
Como hemos creado un método llamado printStream. Aceptará dos argumentos. El primer argumento es el elemento DOM con referencia al cual se agregarán los datos y el segundo argumento es la información o flujo que quiero agregar. Ahora podemos inyectar este servicio en el componente y usar este método:
from-event.component.ts
ngAfterViewInit() { let count = 1; fromEvent(this.addBtn.nativeElement, "click") .subscribe((res) => { this._printService.printStream( "elementContainer", "Book " + count++); }) }
Una variable de conteo que hemos tomado para distinguir entre flujos. Continuará agregando enteros autoincrementados con «Libro». Aquí, en la línea «this._printService.printStream(‘elementContainer’, ‘Book ‘ + count++)», indicamos dónde se debe agregar y qué se debe agregar.
Código definitivo:
from-event.component.html
<!-- To display the data/stream on UI we will keep on adding each stream as a list item in ul below --> <ul id="elementContainer"></ul> <!--Button which will create a stream--> <button #addBtn>Add Book</button>
from-event.component.ts
import { Component, ElementRef, OnInit, ViewChild } from "@angular/core"; import { fromEvent } from "rxjs"; import { PrintServiceService } from "../print-service.service"; @Component({ selector: "app-from-event", templateUrl: "./from-event.component.html", styleUrls: ["./from-event.component.css"], }) export class FromEventComponent implements OnInit { @ViewChild("addBtn", { static: true }) addBtn: ElementRef; constructor(private _printService: PrintServiceService) {} ngOnInit() {} ngAfterViewInit() { let count = 1; fromEvent(this.addBtn.nativeElement, "click").subscribe((res) => { this._printService.printStream("elementContainer", "Book " + count++); }); } }
print-service.service.ts
import { Injectable } from "@angular/core"; @Injectable({ providedIn: "root", }) export class PrintServiceService { constructor() {} printStream(containerName, stream) { // Creating li element in run time let element = document.createElement("li"); element.innerText = stream; // Appending li to ul document.getElementById(containerName).appendChild(element); } }
app.component.html
... <app-from-event></app-from-event>
Salida: puede ver las transmisiones que se tratan con cada clic del mouse. En próximos artículos, aprenderemos sobre Intervalo y Temporizador. Lo cual no es más que otra forma de crear Observable con facilidades adicionales. Espero que esto ayude.
Publicación traducida automáticamente
Artículo escrito por Tanzeel Mirza y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA