首页 文章

Angular 2“time ago”pipe

提问于
浏览
24

我正在尝试为我的Angular 2应用程序创建一个'time ago'管道 .

它应该将日期转换为字符串,例如“5分钟前”或“60秒前” . 它到目前为止工作得很好,但在第一次计算后它没有更新 . 如果给定日期是例如5秒前,它显示'5秒前',但在此之后永远不会改变 .

我已经尝试将管道的“纯”值设置为false但这没有帮助 .

这是我的代码:

import {Pipe, PipeTransform} from 'angular2/core';

@Pipe({
  name: 'messageTime',
  pure: false
})
export class MessageTimePipe implements PipeTransform {
  transform(value: Date, []): string {
    var result: string;

    // current time
    let now = new Date().getTime();

    // time since message was sent in seconds
    let delta = (now - value.getTime()) / 1000;

    // format string
    if (delta < 10) {
      result = 'jetzt';
    } else if (delta < 60) { // sent in last minute
      result = 'vor ' + Math.floor(delta) + ' Sekunden';
    } else if (delta < 3600) { // sent in last hour
      result = 'vor ' + Math.floor(delta / 60) + ' Minuten';
    } else if (delta < 86400) { // sent on last day
      result = 'vor ' + Math.floor(delta / 3600) + ' Stunden';
    } else { // sent more than one day ago
      result = 'vor ' + Math.floor(delta / 86400) + ' Tagen';
    }

    return result;
  }
}

我正在使用这样的过滤器:

打字稿:

import {Component, Input} from 'angular2/core';
import {MessageTimePipe} from '../../pipes/message-time.pipe';

@Component({
  selector: 'message-item',
  pipes: [MessageTimePipe],
  templateUrl: 'build/components/message-item/message-item.component.html'
})
export class MessageItemComponent {
  @Input()
  message: JSON;

  date: Date;

  ngOnInit() {

   this.date = new Date(2016, 3, 16, 12, 49, 10);
  }
}

HTML:

<p class="time">
  {{ date | messageTime }}
</p>

7 回答

  • 0

    最后让它工作,非常具有挑战性,需要间隔调整:)

    import {Pipe, ChangeDetectorRef} from 'angular2/core';
    import {Observable} from 'rxjs/Observable';
    import {AsyncPipe} from 'angular2/common';
    
    @Pipe({
        name: 'messageTime',
        pure: false
    })
    export class MessageTimePipe extends AsyncPipe
    {
        value:Date;
        timer:Observable<string>;
    
        constructor(ref:ChangeDetectorRef)
        {
            super(ref);
        }
    
        transform(obj:any, args?:any[]):any
        {
            if (obj instanceof Date)
            {
                this.value = obj;
    
                if(!this.timer)
                {
                    this.timer = this.getObservable();
                }
    
                return super.transform(this.timer, args);
            }
    
            return super.transform(obj, args);
        }
    
        private getObservable()
        {
            return Observable.interval(1000).startWith(0).map(()=>
            {
                var result:string;
                // current time
                let now = new Date().getTime();
    
                // time since message was sent in seconds
                let delta = (now - this.value.getTime()) / 1000;
    
                // format string
                if (delta < 10)
                {
                    result = 'jetzt';
                }
                else if (delta < 60)
                { // sent in last minute
                    result = 'vor ' + Math.floor(delta) + ' Sekunden';
                }
                else if (delta < 3600)
                { // sent in last hour
                    result = 'vor ' + Math.floor(delta / 60) + ' Minuten';
                }
                else if (delta < 86400)
                { // sent on last day
                    result = 'vor ' + Math.floor(delta / 3600) + ' Stunden';
                }
                else
                { // sent more than one day ago
                    result = 'vor ' + Math.floor(delta / 86400) + ' Tagen';
                }
                return result;
            });
        };
    }
    
  • 4

    我刚用过这个:

    https://www.npmjs.com/package/time-ago-pipe

    npm install time-ago-pipe --save
    

    然后在@NgModule中你想用它:

    import {TimeAgoPipe} from 'time-ago-pipe
    
    @NgModule({
        imports: [... etc ...],
        declarations: [AppComponent, ...etc..., TimeAgoPipe],
        bootstrap: [AppComponent]
    })
    

    在模板中:

    <span>{{your_date | timeAgo}}</span>
    

    Don't reinvent the wheel, unless you plan on learning more about wheels.

  • 0

    根据@kemsky的优秀答案,我实现了Pipe的一个变种,修复了一些实现问题:

    • 将在角度2最终及以后正常工作

    • 在销毁时停止轮询

    • 使用简单的退避来减少与输出一致的轮询间隔

    您可以在此要点中找到完整的管道规格代码:https://gist.github.com/JohannesRudolph/8e6de056d9e33353f940d9da9e6ffd82

  • 23

    我认为它与你的管道无关,而是与Angular2检测到变化的方式有关 . 它根据引用检测更改,即绑定引用是否更改,而不是更新它们中的元素 .

    请参阅以下示例:

    @Component({
      selector: 'my-app',
      template: `
        <div>{{val | pdate}}</div>
      `,
      pipes: [ DatePipe ]
    })
    export class AppComponent {
      constructor() {
        this.val = new Date();
    
        setTimeout(() => {
          this.val = new Date(); // Updates view
        }, 1000);
    
        setTimeout(() => {
          this.val.setTime((new Date().getTime()); // Doesn't update view
        }, 2000);
      }
    }
    

    见thisx plunkr:https://plnkr.co/edit/kJdi1wx0iu9tDx8yTmRx?p=preview .

  • 0

    你需要更新'date'引用来触发Angular2的变化检测,例如,如Thierry指出的那样 setTimeout(()=>this.date=new Date(), period) .

    你真的需要每秒更新一次吗?根据您的使用情况,每60秒更新一次可能就足够了,并且可以在前60秒内显示“刚刚”或“不到一分钟前” .

    但如果你真的想要秒,你只需要在前60秒内每秒更新一次 . 然后 setTimeout(1000) 可以成为 setTimeout(60000) ,以最大限度地减少开销 .

  • 18

    获得AngularJs2的时间

    您需要运行此命令 npm install time-ago-pipe --save 以在角应用程序中安装超时的npm软件包 ex : PS D:\D\TimeAgo> npm install time-ago-pipe --save. 运行此命令后,将添加软件包 . Image shows how to add import from 'time-ago-pipe'; in app.module and put TimeAgoPipe in Declarations [从组件传递输入o/p

  • 0

    一个 moment.js 解决方案 . 在Angular 6中工作/测试:

    import { ChangeDetectorRef, NgZone, Pipe, PipeTransform } from '@angular/core';
    import * as moment from 'moment';
    
    moment.locale("de"); // set your language
    
    @Pipe({
        name:'timeago',
        pure:false
    })
    export class TimeagoPipe implements PipeTransform {    
        private timer: number;
        constructor(private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone) {}
        transform(value:string) {
            this.removeTimer();
            let d = new Date(value);
            let now = new Date();
            let seconds = Math.round(Math.abs((now.getTime() - d.getTime())/1000));
            let timeToUpdate = (Number.isNaN(seconds)) ? 1000 : this.getSecondsUntilUpdate(seconds) *1000;
            this.timer = this.ngZone.runOutsideAngular(() => {
                if (typeof window !== 'undefined') {
                    return window.setTimeout(() => {
                        this.ngZone.run(() => this.changeDetectorRef.markForCheck());
                    }, timeToUpdate);
                }
                return null;
            });
    
        return moment(d).fromNow();
    
        }
        ngOnDestroy(): void {
            this.removeTimer();
        }
        private removeTimer() {
            if (this.timer) {
                window.clearTimeout(this.timer);
                this.timer = null;
            }
        }
        private getSecondsUntilUpdate(seconds:number) {
            let min = 60;
            let hr = min * 60;
            let day = hr * 24;
            if (seconds < min) { // less than 1 min, update every 2 secs
                return 2;
            } else if (seconds < hr) { // less than an hour, update every 30 secs
                return 30;
            } else if (seconds < day) { // less then a day, update every 5 mins
                return 300;
            } else { // update every hour
                return 3600;
            }
        }
    }
    

相关问题