2017-11-11 108 views
1

我需要在我的Angular 4/5应用程序中构建一个TimeZone选择器。当用户更改时区时,我希望页面上的所有显示时间值立即更新。实现动态时区选择器Angular 2/4/5

我正打算使用:

  • momentjs使用angular2-momentangular-moment-timezone时区的支持。
  • 要格式化日期,请使用amLocal管道,然后是其他管道。
  • 当用户选择不同的时区,我打算叫moment.tz.setDefault(_timezone)

通过以上的值从被格式化为新的时区了这一点,而目前显示的时间值不会改变。由于输入值没有改变,角度更改检测机制不会更新显示的时间值。

由于性能开销(考虑时区更改不是一个频繁的活动),我不想创建“不纯”管道。

作为后备我可以创建一个管道(或使用现有的),将当前时区作为参数。它确实有效,但我需要将当前时区值传递给每个组件和模板。

我一直无法找到角度变化检测的方法,即使没有值的变化,也会发生变化。

任何建议将受到欢迎。

+2

*我一直没能找到一种方式,角度变化检测相信有变化,即使没有*值的变化:是你有:这就是所谓的不纯管道。 –

+0

双重绑定可能是您的最佳选择? –

+1

当你说“不更新显示的时间值”时,你的意思是什么?你的意思是这些值代表“现在”,你希望它们像时钟一样向前跳动?如果是这样,你需要一个某种计时器。 –

回答

2

管道不是组件(显而易见),它们没有自己的更改检测机制,但pure标志除外。所以有两种方法可以达到预期的效果:

  1. 使用智能不纯管道将跟踪以前的值和以前的格式化结果。角的AsyncPipe(这是不纯实际上,如果有另一种方式来这样做,那么我相信这将是由纯)被以这种方式实现:

    if (value !== this.value || this.timeZoneChanged) 
    { 
        this.value = value; 
        this.formattedValue = ... render value ...; 
    } 
    return this.formattedValue; 
    

    您可以在github上浏览AsyncPipe源代码。

  2. 使用自定义组件呈现日期,即自定义ControlValueAccessor
1

例如,当使用例如ngx-translate时,切换语言意味着获取新的翻译。正如你可以看到here他们使用不纯的管道,正如你所说的暗示性能问题。

我想象的另一种方式是定义一个可用于整个应用程序的组件DateComponent。这样,而不是在您的html {{ value | formatDate }}你有<custom-date [date]="new Date()"></custom-date>

在您的自定义日期组件将看起来像这样

@Component({ 
    selector: 'custom-date', 
    template: '<span>{{ formatedDate }}</span>' 
}) 
export class DateComponent { 
    @Input() date: string; 
    timezone: string; 
    formatedDate: string; 
    constructor(private userService: UserService) {} 

    ngOnInit(){ 
    this.timezone = this.userService.getTimeZone(); 
    this.updateValue(); 
    this.userService.onTimezoneChange() 
     .subscribe(timezone => { 
     this.timezone = timezone; 
     this.updateValue(); 
     }); 
    } 

    updateValue() { 
    // Do your formatting the way you want 
    this.formatedDate = moment(this.date).tz(this.timezone).format(); 
    } 
}