最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2 periodically refresh view - Stack Overflow

programmeradmin1浏览0评论

I'm displaying a list of items with their relative creation dates using moment.js .fromNow() like so:

getRelativeDate(date: string): string {
  return moment(date, 'YYYY-MM-DD HH:mm:ss').fromNow();
}

<div class="created">{{getRelativeDate(item.created)}}</div>

And here's what it looks like:

But unless I interact with the item somehow it stays the same after initial load, which makes sense, since data isn't changing, current time is.

How can I force-refresh these values? Every minute would suffice.

I'm displaying a list of items with their relative creation dates using moment.js .fromNow() like so:

getRelativeDate(date: string): string {
  return moment(date, 'YYYY-MM-DD HH:mm:ss').fromNow();
}

<div class="created">{{getRelativeDate(item.created)}}</div>

And here's what it looks like:

But unless I interact with the item somehow it stays the same after initial load, which makes sense, since data isn't changing, current time is.

How can I force-refresh these values? Every minute would suffice.

Share Improve this question asked Nov 6, 2017 at 23:54 abfaridabfarid 5556 silver badges13 bronze badges 1
  • This will depend on if your item data is async or not. You can create a setInterval() in ngOnInit() if the data is not async, if the data is async you can create the setInterval() after the data is fetched. – Z. Bagley Commented Nov 7, 2017 at 0:02
Add a ment  | 

4 Answers 4

Reset to default 5

Surprised no one mentioned creating a pipe for this?

import { Pipe, PipeTransform } from '@angular/core';

import moment from 'moment';

@Pipe({
  name: 'dateTimeFormat',
  pure: false,
})
export class DateTimeFormatPipe implements PipeTransform {
  transform(date: string, format: string = 'YYYY-MM-DD HH:mm:ss'): string {
    return moment(date, format).fromNow();
  }
}

This keeps your ponent clean by offloading the logic into a Pipe.

<ul>
  <li *ngFor="let date of dates">
    {{ date | dateTimeFormat:'YYYY-MM-DD HH:mm:ss'}}
  </li>
</ul>

Whats cool is the format is optional and can be reused throughout your application.

Then to update the ponent periodically refresh call setInterval. You also need to invoke ChangeDetectorRef and call detectChanges based on your ChangeDetectionStrategy. Better yet, detach the ponent pletely.

Live Example https://stackblitz./edit/angular-cli-moment-pipe

Helpful set of Moment Pipes https://github./urish/angular2-moment/

Go with a setInterval.

We'll need the ChangeDetectorRef to do this.

import {OnInit, OnDestroy, ChangeDetectorRef} from '@angular/core';

export class Listponent implements OnInit, OnDestroy {

   intervalHolder: any;

   constructor(private _changeDetectorRef: ChangeDetectorRef) {
   }

   ngOnInit(): void {
     this.intervalHolder = setInterval(() => {
       // Let's refresh the list.
       this._changeDetectorRef.markForCheck();
     }, 1000 * 60); // 1 minute
   }

   ngOnDestroy(): void {
      clearInterval(this.intervalHolder);
   }
}

If your data isn't async you can create a setInterval() in your ngOnInit() and then clear it ngOnDestroy(). Assuming your created dates are stored in an array named items under key created:

ponent.ts

myFromNowInterval: any;
myFromNow = Array(this.items.length).fill('');

ngOnInit() {
  this.myFromNowInterval = setInterval( () => {
    this.items.forEach( (item, index) => this.myFromNow[index] = this.getRelativeDate(item) )
  }, 60000);
}

ngOnDestroy() {
  clearInterval(this.myFromNowInterval);
}

ponent.html

<div *ngFor="item of items; let i = index;">
  <div class="created">{{ myFromNow[i] }}</div>
</div>

This will update myFromNow array every minute, and aligns the index of your new array to the DOM.

I think it's sufficient to just put an observable interval on the ponent, to trigger change detection.

triggerCD$;

ngOnInit() {
  this.triggerCD$ = Observable.interval(60000)
}

Testing with this

<span>{{ now() }}</span>

now() {
  const now: any = new Date();
  return (now - this.start)
}

With no trigger, display does not change.
With trigger, now() updates on the template (although no direct link to trigger).

发布评论

评论列表(0)

  1. 暂无评论