What is the correct (canonical) way to display current time in angular 4 change detection system?
The problem is as follows: current time changes constantly, each moment, by definition. But it is not detectable by Angular 4 change detection system. For this reason, in my opinion, it's necessary to explicitly call ChangeDetectorRef::detectChanges
. However, in the process of calling this method, current time naturally changes its value. This leads to ExpressionChangedAfterItHasBeenCheckedError
. In the following example (see live) this error appears withing a few seconds after loading the 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);
}
}
Use arrow function.
If you want to format this on html page, use it like this:
As per Angular documentation on the
DatePipe
Link,Date.now()
can be used.First of all you don't need to call
ChangeDetectorRef.detectChanges()
inside your interval, because angular is usingZone.js
which monkey patches the browserssetInteral
method with its own. Therefore angular is well aware of the changes happening during an interval.You should set the time inside your interval like this:
If you want to update the DOM at a very high rate, you should use
runOutsideAngular
fromNgZone
and update the DOM manually using theRenderer2
.For example:
Actually, you don't need any library for this simple task. If you are doing in your angular project with angular 6+ then import formatDate from the common package and pass other data. Here is a sample:
Here is a stackblitz link, you can edit here: https://stackblitz.com/edit/angular-h63y8e