Molloch
Molloch

Reputation: 2381

Angular 2+ - Refresh displayed time duration periodically

I am using the moment library to create a human readable timer in Angular through a pipe. Basically my pipe takes a date and returns something like "5 minutes ago" instead of "2021-01-05 10:45AM".

The data in my list is static, the date/time for each item being loaded from a database:

ts:

tasks = [{dueDate: "2021-01-05 10:45AM", message: "Put the bins out"}, 
         {dueDate: "2021-01-05 11:30AM", message: "Meeting with Jack"}];

html:

<div *ngFor="let task of tasks">
   {{task.message}} - {{task.dueDate | dateh}}
</div>

result:

Put the bins out - 5 minutes ago
Meeting with Jack - in 50 minutes

I want to create a timer that will refresh the UI, so that in one minute we get:

Put the bins out - 6 minutes ago
Meeting with Jack - in 49 minutes

Without reloading the data or refreshing every other component on the page. I have a 30 second timer created with ngrx:

this.timerSub = timer(30000, 30000).subscribe((d) =>
    console.log("Timer is now", d)
);

But because the data hasn't actually changed (just the pipe transform will now return a different string), I can't seem to get the component display to detect anything is different.

What is the best way to force the UI to re-run the pipe transform and update the display?

Upvotes: 0

Views: 198

Answers (1)

Alvin Saldanha
Alvin Saldanha

Reputation: 916

Based on this angular documentation, You can convert your pipe to an impure pipe. Then the change detection should fire.

To execute a custom pipe after a change within a composite object, such as a change to an element of an array, you need to define your pipe as impure to detect impure changes. Angular executes an impure pipe every time it detects a change with every keystroke or mouse movement.

@Pipe({
  name: 'yourPipeName',
  pure: false
})

While an impure pipe can be useful, be careful using one. A long-running impure pipe could dramatically slow down your app.

Upvotes: 1

Related Questions