Volviendo con un poco de angular, me salio la necesidad de crear un reloj en angular, para esto necesitamos conocer unos conceptos básicos de rxjs.
Porque usar rxjs y no un interval
Una de las maneras mas sencillas es usar un setInterval de javascript que cada segundo ejecuta una función y bueno ya tenemos un reloj, pero para no romper la armonía de angular y dejar de usar el hilo principal vamos a usar Observables y un evento llamado timer.
Como ya sabemos el Observable lo que hace es que usa un hilo asíncrono para hacer una tarea especifica y te avisa cuando existe un cambio.
timer seria como un interval en rx, le decimos cada cuanto va a ejecutarse y lo repite cada x tiempo.
como podemos ver tenemos un reloj digital para esto vamos a hacer un servicio para podernos suscribirnos y tener la información de la fecha y hora.
Creación de reloj en angular
para el servicio vamos a crear lo siguiente:
- modelo para información de datos (hora, día y fecha)
- VARIABLES Observables
- llenar variables y conversión a objeto observable
Servicio de reloj
import { Injectable } from '@angular/core'; import {timer, Observable, Subject} from 'rxjs'; import {map, shareReplay} from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class valorReloj { hora: number; minutos: string; ampm: string; diadesemana: string; diaymes: string; segundo: string; } export class XsegundoService { clock: Observable <Date>; infofecha$ = new Subject<valorReloj>(); vr: valorReloj; ampm: string; hours: number; minute: string; weekday: string; months: string; constructor() { this.clock = timer(0,1000).pipe(map(t => new Date()),shareReplay(1)); } getInfoReloj(): Observable<valorReloj>{ this.clock.subscribe(t => { this.hours = t.getHours() % 12; this.hours = this.hours ? this.hours : 12; this.vr = { hora: this.hours, minutos: (t.getMinutes() < 10) ? '0' + t.getMinutes() : t.getMinutes().toString(), ampm: t.getHours() > 11 ? 'PM' : 'AM', diaymes: t.toLocaleString('es-MX', { day: '2-digit', month: 'long' }).replace('.', '').replace('-', ' '), diadesemana: t.toLocaleString('es-MX', { weekday: 'long' }).replace('.', ''), segundo: t.getSeconds() < 10 ? '0' + t.getSeconds() : t.getSeconds().toString() } this.infofecha$.next(this.vr); }); return this.infofecha$.asObservable(); } }
tenemos que recordar lo siguiente, pueden leer este articulo, pero en resumen:
- subject: que es el encargado de generar y emitir los eventos de actualización del almacén de datos.
- observable: es un objeto que permite observar los eventos emitidos por el subject.
- suscripción: generada a partir del observable.
- shareReplay: pueden suscribirse y enviara la ultima información a los suscritos para que no exista un retraso
- toLocaleString:
retorna una cadena que contiene una representación del número acorde al idioma. - next: avisa a observador que existe un cambio
- variable$: una variable con el signo $ indica que es un observable
con esto ya podemos suscribirnos en cualquier parte y poder crear un reloj en angular.
Al ser un Date, nos trae hora , minutos, segundos, fecha, dia y año, lo que hice fue un modelo y extraje lo que mas me interesaba y en formato de 12 horas.
vista del componente clock.
<div class="clock"> <p>{{dia}}</p> <p>{{fecha}}</p> <div class="hours"> <div class="horas"> <span class="mishoras">{{hora}}:{{minutos}}</span> <span class="ampm">{{ampm}}</span> </div> </div> <div></div> <span></span> <span class="segundos">{{segundos}}</span> </div>
css
.clock { display: grid; grid-gap: 1px 5px; grid-template-columns: auto auto auto; justify-content: center; align-content: center; align-items: center; align-self: center; width: 100%; } .clock p { color: #666; font-size: 2rem; } .hours { grid-column-start: 1; grid-column-end: 3; } .horas { display: flex; flex-wrap: nowrap; flex-direction: column-reverse; justify-content: center; align-items: baseline; } span { color: #777777; } .mishoras { font-weight: bold; font-size: 10rem; } .ampm { font-size: 1.4rem; font-weight: 200; } .segundos { width: 100%; text-align: right; font-size: 0.8rem; font-size: 100; }
Como llamar nuestro servicio para crear un reloj en angular 7
import { Component, OnInit } from '@angular/core'; import {XsegundoService, valorReloj} from '../xsegundo.service'; import { Observable } from 'rxjs'; @Component({ selector: 'app-clock', templateUrl: './clock.component.html', styleUrls: ['./clock.component.css'] }) export class ClockComponent implements OnInit { datos$: Observable<valorReloj>; hora: number; minutos: string; dia: string; fecha: string; ampm: string; segundos: string; constructor(private segundo: XsegundoService) { } ngOnInit() { this.datos$=this.segundo.getInfoReloj(); this.datos$.subscribe(x => { this.hora = x.hora; this.minutos = x.minutos; this.dia = x.diadesemana; this.fecha = x.diaymes; this.ampm = x.ampm; this.segundos = x.segundo }); } }
al ser un observable la función getInfoReloj nos regresara un cambio cada segundo (recuerden que así configuramos el timer) y para obtener el objeto que manda tenemos que suscribirnos a ellos.
al final solo llamamos a nuestro componente
<app-clock class="mreloj"></app-clock>
Como es costumbre dejare los links del repositorio y del post en live
[…] Si no reconoces o no sabes que es Subject en angular te recomiendo ver este post. […]
[…] que tenemos observables y subjects como el ejemplo pasado, estos también nos ayuda para pasar un mensaje de punto a […]