web-dev-qa-db-fra.com

Affichage angulaire 4 heure actuelle

Quelle est la manière correcte (canonique) d'afficher l'heure actuelle dans le système de détection de changements angulaires 4?

Le problème est le suivant: l’heure actuelle change constamment, à chaque instant, par définition. Mais il n'est pas détectable par le système de détection de changement angulaire 4. Pour cette raison, à mon avis, il est nécessaire d'appeler explicitement ChangeDetectorRef::detectChanges. Cependant, lors de l'appel de cette méthode, l'heure actuelle change naturellement de valeur. Cela conduit à ExpressionChangedAfterItHasBeenCheckedError. Dans l'exemple suivant ( see live ), cette erreur apparaît quelques secondes après le chargement de la page:

import { Component, ChangeDetectorRef } from '@angular/core';
@Component({
    selector: 'my-app',
    template: `{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />
        {{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}<br />{{ now }}`
})
export class AppComponent {
    get now() : string { return Date(); }
    constructor(cd: ChangeDetectorRef) {
        setInterval(function() { cd.detectChanges(); }, 1);
    }
}
8
BOPOHOB

Tout d'abord, vous n'avez pas besoin d'appeler ChangeDetectorRef.detectChanges() dans votre intervalle, car angular utilise Zone.js qui monkey corrige la méthode setInteral du navigateur avec sa propre méthode. Par conséquent, angular est bien conscient des changements qui se produisent pendant un intervalle.

Vous devriez définir le temps dans votre intervalle comme ceci:

import { Component } from '@angular/core';
@Component({
    selector: 'my-app',
    template: `{{ now }}`
})
export class AppComponent {
    public now: Date = new Date();

    constructor() {
        setInterval(() => {
          this.now = new Date();
        }, 1);
    }
}

Mais vous ne devriez pas mettre à jour l'heure avec un débit aussi élevé, car cela conduirait à une performance médiocre, car chaque fois que la date est mise à jour, angular effectue une détection de changement sur l'arborescence des composants.

Si vous souhaitez mettre à jour le DOM très rapidement, vous devez utiliser runOutsideAngular à partir de NgZone et mettre à jour le DOM manuellement à l'aide du Renderer2.

Par exemple:

@Component({
  selector: 'my-counter',
  template: '<span #counter></span>'
})
class CounterComponent implements OnChange {
  public count: number = 0;

  @ViewChild('counter')
  public myCounter: ElementRef;

  constructor(private zone: NgZone, private renderer: Renderer2) {
    this.zone.runOutsideAngular(() => {
      setInterval(() => {
        this.renderer.setProperty(this.myCounter.nativeElement, 'textContent', ++this.count);
      }, 1);
    });
  }
}
15
cyr-x

Selon la documentation angulaire sur la variable DatePipeLink , Date.now() peut être utilisée.

import { Component } from '@angular/core';
@Component({
    selector: 'my-app',
    template: `{{ now | date:'HH:mm:ss'}}`
})
export class AppComponent {
    now:number;

    constructor() {
        setInterval(() => {
          this.now = Date.now();
        }, 1);
    }
}
6
mrOak
CurrentTime: any;
  constructor() {
    setInterval(() => {
      this.CurrentTime = new Date().getHours() + ':' + new Date().getMinutes() + ':'+  new Date().getSeconds()}, 1);
  }
0
Bruce Smile