Skip to content

Commit

Permalink
fix(module:date-picker): support changing language at runtime (NG-ZOR…
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsoncook authored and vthinkxie committed Jul 2, 2018
1 parent 3e5c706 commit 8df9359
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 10 deletions.
45 changes: 37 additions & 8 deletions components/date-picker/abstract-picker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import {
EventEmitter,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { InputBoolean } from '../core/util/convert';
import { NzDatePickerI18nInterface } from '../i18n/nz-i18n.interface';
import { NzI18nService } from '../i18n/nz-i18n.service';
Expand All @@ -20,7 +23,7 @@ const POPUP_STYLE_PATCH = { 'position': 'relative' }; // Aim to override antd's
/**
* The base picker for all common APIs
*/
export abstract class AbstractPickerComponent implements OnInit, OnChanges, ControlValueAccessor {
export abstract class AbstractPickerComponent implements OnInit, OnChanges, OnDestroy, ControlValueAccessor {
// --- Common API
@Input() @InputBoolean() nzAllowClear: boolean = true;
@Input() @InputBoolean() nzAutoFocus: boolean = false;
Expand Down Expand Up @@ -52,28 +55,42 @@ export abstract class AbstractPickerComponent implements OnInit, OnChanges, Cont
this.nzValue = this.isRange ? [] : null;
}

protected destroyed$: Subject<void> = new Subject();
protected isCustomPlaceHolder: boolean = false;

constructor(protected i18n: NzI18nService) {
}

ngOnInit(): void {
// Default locale (NOTE: Place here to assign default value due to the i18n'locale may change before ngOnInit)
// Subscribe the every locale change if the nzLocale is not handled by user
if (!this.nzLocale) {
this.nzLocale = this.i18n.getLocaleData('DatePicker', {});
this.i18n.localeChange
.pipe(takeUntil(this.destroyed$))
.subscribe(() => this.setLocale());
}

// Default value
this.initValue();

// Default placeholder
if (!this.nzPlaceHolder) {
this.nzPlaceHolder = this.isRange ? this.nzLocale.lang.rangePlaceholder : this.nzLocale.lang.placeholder;
}
}

ngOnChanges(changes: SimpleChanges): void {
if (changes.nzPopupStyle) { // Always assign the popup style patch
this.nzPopupStyle = this.nzPopupStyle ? { ...this.nzPopupStyle, ...POPUP_STYLE_PATCH } : POPUP_STYLE_PATCH;
}

// Mark as customized placeholder by user once nzPlaceHolder assigned at the first time
if (changes.nzPlaceHolder && changes.nzPlaceHolder.firstChange && typeof this.nzPlaceHolder !== 'undefined') {
this.isCustomPlaceHolder = true;
}

if (changes.nzLocale) { // The nzLocale is currently handled by user
this.setDefaultPlaceHolder();
}
}

ngOnDestroy(): void {
this.destroyed$.next();
this.destroyed$.complete();
}

closeOverlay(): void {
Expand Down Expand Up @@ -138,6 +155,18 @@ export abstract class AbstractPickerComponent implements OnInit, OnChanges, Cont
// | Internal methods
// ------------------------------------------------------------------------

// Reload locale from i18n with side effects
private setLocale(): void {
this.nzLocale = this.i18n.getLocaleData('DatePicker', {});
this.setDefaultPlaceHolder();
}

private setDefaultPlaceHolder(): void {
if (!this.isCustomPlaceHolder && this.nzLocale) {
this.nzPlaceHolder = this.isRange ? this.nzLocale.lang.rangePlaceholder : this.nzLocale.lang.placeholder;
}
}

private formatDate(date: CandyDate): string {
return date ? this.i18n.formatDateCompatible(date.nativeDate, this.nzFormat) : '';
}
Expand Down
24 changes: 22 additions & 2 deletions components/date-picker/date-picker.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import * as isSameDay from 'date-fns/is_same_day';

import { dispatchKeyboardEvent, dispatchMouseEvent } from '../core/testing';
import en_US from '../i18n/languages/en_US';
import { NzI18nModule } from '../i18n/nz-i18n.module';
import { NzI18nService } from '../i18n/nz-i18n.service';
import { NzDatePickerModule } from './date-picker.module';
import { PickerResultSingle } from './standard-types';

Expand All @@ -21,10 +24,11 @@ describe('NzDatePickerComponent', () => {
let debugElement: DebugElement;
let overlayContainer: OverlayContainer;
let overlayContainerElement: HTMLElement;
let i18nService: NzI18nService;

beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
imports : [ FormsModule, NoopAnimationsModule, NzDatePickerModule ],
imports : [ FormsModule, NoopAnimationsModule, NzDatePickerModule, NzI18nModule ],
providers : [],
declarations: [
NzTestDatePickerComponent
Expand All @@ -40,9 +44,10 @@ describe('NzDatePickerComponent', () => {
debugElement = fixture.debugElement;
});

beforeEach(inject([ OverlayContainer ], (oc: OverlayContainer) => {
beforeEach(inject([ OverlayContainer, NzI18nService ], (oc: OverlayContainer, i18n: NzI18nService) => {
overlayContainer = oc;
overlayContainerElement = oc.getContainerElement();
i18nService = i18n;
}));

afterEach(() => {
Expand All @@ -67,6 +72,21 @@ describe('NzDatePickerComponent', () => {
expect(getPickerContainer()).toBeNull();
}));

it('should support changing language at runtime', fakeAsync(() => {
fixture.detectChanges();
expect(getPickerTrigger().placeholder).toBe('请选择日期');
i18nService.setLocale(en_US);
fixture.detectChanges();
expect(getPickerTrigger().placeholder).toBe('Select date');

dispatchMouseEvent(getPickerTrigger(), 'click');
fixture.detectChanges();
tick(500);
fixture.detectChanges();
expect((queryFromOverlay('.ant-calendar-date-input-wrap input.ant-calendar-input') as HTMLInputElement).placeholder).toBe('Select date');
expect(queryFromOverlay('.ant-calendar-table .ant-calendar-column-header-inner').textContent).toContain('Su');
}));

/* Issue https://github.com/NG-ZORRO/ng-zorro-antd/issues/1539 */
it('should be openable after closed by "Escape" key', fakeAsync(() => {
fixture.detectChanges();
Expand Down
11 changes: 11 additions & 0 deletions components/date-picker/demo/basic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import * as getISOWeek from 'date-fns/get_iso_week';
import { en_US, zh_CN, NzI18nService } from 'ng-zorro-antd';

@Component({
selector: 'nz-demo-date-picker-basic',
Expand All @@ -11,6 +12,8 @@ import * as getISOWeek from 'date-fns/get_iso_week';
<nz-range-picker [(ngModel)]="dateRange" (ngModelChange)="onChange($event)" nzShowTime></nz-range-picker>
<br>
<nz-week-picker [(ngModel)]="date" (ngModelChange)="getWeek($event)" nzPlaceHolder="Select week"></nz-week-picker>
<br>
<button nz-button nzType="default" (click)="changeLanguage()">Switch language for all pickers</button>
`,
styles : [ `
nz-date-picker, nz-month-picker, nz-range-picker, nz-week-picker {
Expand All @@ -22,6 +25,9 @@ import * as getISOWeek from 'date-fns/get_iso_week';
export class NzDemoDatePickerBasicComponent {
date = null; // new Date();
dateRange = []; // [ new Date(), addDays(new Date(), 3) ];
isEnglish = false;

constructor(private i18n: NzI18nService) {}

onChange(result: Date): void {
console.log('onChange: ', result);
Expand All @@ -30,4 +36,9 @@ export class NzDemoDatePickerBasicComponent {
getWeek(result: Date): void {
console.log('week: ', getISOWeek(result));
}

changeLanguage(): void {
this.i18n.setLocale(this.isEnglish ? zh_CN : en_US);
this.isEnglish = !this.isEnglish;
}
}

0 comments on commit 8df9359

Please sign in to comment.