Skip to content

Commit

Permalink
feat(module:time-picker): support setting status (#7473)
Browse files Browse the repository at this point in the history
* feat(module:time-picker): support setting status

* feat(module:time-picker): add tests
  • Loading branch information
simplejason committed May 31, 2022
1 parent c3d0874 commit 0d8249b
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 6 deletions.
3 changes: 2 additions & 1 deletion components/time-picker/demo/module
@@ -1,4 +1,5 @@
import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzSpaceModule } from 'ng-zorro-antd/space';

export const moduleList = [ NzTimePickerModule, NzButtonModule ];
export const moduleList = [ NzTimePickerModule, NzButtonModule, NzSpaceModule ];
14 changes: 14 additions & 0 deletions components/time-picker/demo/status.md
@@ -0,0 +1,14 @@
---
order: 10
title:
zh-CN: 自定义状态
en-US: Status
---

## zh-CN

使用 `nzStatus` 为 TimePicker 添加状态,可选 `error` 或者 `warning`

## en-US

Add status to TimePicker with `nzStatus`, which could be `error` or `warning`.
12 changes: 12 additions & 0 deletions components/time-picker/demo/status.ts
@@ -0,0 +1,12 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-time-picker-status',
template: `
<nz-space nzDirection="vertical">
<nz-time-picker *nzSpaceItem nzStatus="error"></nz-time-picker>
<nz-time-picker *nzSpaceItem nzStatus="warning">></nz-time-picker>
</nz-space>
`
})
export class NzDemoTimePickerStatusComponent {}
2 changes: 2 additions & 0 deletions components/time-picker/doc/index.en-US.md
Expand Up @@ -44,6 +44,8 @@ import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
| `[nzHourStep]` | interval between hours in picker | `number` | `1` ||
| `[nzMinuteStep]` | interval between minutes in picker | `number` | `1` ||
| `[nzSecondStep]` | interval between seconds in picker | `number` | `1` ||
| `[nzSize]` | width of time picker box | `'large' \| 'small' \| 'default'` | `'default'` |
| `[nzStatus]` | Set validation status | `'error' \| 'warning'` | - |
| `[nzOpen]` | whether to popup panel, double binding | `boolean` | `false` |
| `[nzPlaceHolder]` | display when there's no value | `string` | `"Select a time"` |
| `[nzPopupClassName]` | className of panel | `string` | `''` ||
Expand Down
2 changes: 2 additions & 0 deletions components/time-picker/doc/index.zh-CN.md
Expand Up @@ -45,6 +45,8 @@ import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
| `[nzHourStep]` | 小时选项间隔 | `number` | `1` ||
| `[nzMinuteStep]` | 分钟选项间隔 | `number` | `1` ||
| `[nzSecondStep]` | 秒选项间隔 | `number` | `1` ||
| `[nzSize]` | 时间选择框大小 | `'large'\|'small'\|'default'` | `'default'` |
| `[nzStatus]` | 设置校验状态 | `'error' \| 'warning'` | - |
| `[nzOpen]` | 面板是否打开,可双向绑定 | `boolean` | `false` |
| `[nzPlaceHolder]` | 没有值的时候显示的内容 | `string` | `"请选择时间"` |
| `[nzPopupClassName]` | 弹出层类名 | `string` | `''` ||
Expand Down
62 changes: 60 additions & 2 deletions components/time-picker/time-picker.component.spec.ts
@@ -1,3 +1,4 @@
import { BidiModule, Direction } from '@angular/cdk/bidi';
import { OverlayContainer } from '@angular/cdk/overlay';
import { registerLocaleData } from '@angular/common';
import zh from '@angular/common/locales/zh';
Expand All @@ -8,6 +9,7 @@ import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

import { dispatchFakeEvent, dispatchMouseEvent, typeInElement } from 'ng-zorro-antd/core/testing';
import { NzStatus } from 'ng-zorro-antd/core/types';
import { PREFIX_CLASS } from 'ng-zorro-antd/date-picker';
import { getPickerInput, getPickerOkButton } from 'ng-zorro-antd/date-picker/testing/util';

Expand All @@ -24,9 +26,9 @@ describe('time-picker', () => {
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, FormsModule, NzI18nModule, NzTimePickerModule],
imports: [BidiModule, NoopAnimationsModule, FormsModule, NzI18nModule, NzTimePickerModule],
schemas: [NO_ERRORS_SCHEMA],
declarations: [NzTestTimePickerComponent]
declarations: [NzTestTimePickerComponent, NzTestTimePickerStatusComponent, NzTestTimePickerDirComponent]
});
TestBed.compileComponents();
inject([OverlayContainer], (oc: OverlayContainer) => {
Expand Down Expand Up @@ -292,6 +294,48 @@ describe('time-picker', () => {
});
});

describe('time-picker status', () => {
let testComponent: NzTestTimePickerStatusComponent;
let fixture: ComponentFixture<NzTestTimePickerStatusComponent>;
let timeElement: DebugElement;
beforeEach(() => {
fixture = TestBed.createComponent(NzTestTimePickerStatusComponent);
testComponent = fixture.debugElement.componentInstance;
fixture.detectChanges();
timeElement = fixture.debugElement.query(By.directive(NzTimePickerComponent));
});
it('should className correct with nzStatus', () => {
fixture.detectChanges();
expect(timeElement.nativeElement.classList).toContain('ant-picker-status-error');

testComponent.status = 'warning';
fixture.detectChanges();
expect(timeElement.nativeElement.className).toContain('ant-picker-status-warning');

testComponent.status = '';
fixture.detectChanges();
expect(timeElement.nativeElement.className).not.toContain('ant-picker-status-warning');
});
});

describe('time-picker RTL', () => {
let testComponent: NzTestTimePickerDirComponent;
let fixture: ComponentFixture<NzTestTimePickerDirComponent>;
let timeElement: DebugElement;
beforeEach(() => {
fixture = TestBed.createComponent(NzTestTimePickerDirComponent);
testComponent = fixture.debugElement.componentInstance;
fixture.detectChanges();
timeElement = fixture.debugElement.query(By.directive(NzTimePickerComponent));
});
it('should className correct on dir change', () => {
expect(timeElement.nativeElement.classList).not.toContain('ant-picker-rtl');
testComponent.dir = 'rtl';
fixture.detectChanges();
expect(timeElement.nativeElement.classList).toContain('ant-picker-rtl');
});
});

function queryFromOverlay(selector: string): HTMLElement {
return overlayContainerElement.querySelector(selector) as HTMLElement;
}
Expand Down Expand Up @@ -334,3 +378,17 @@ export class NzTestTimePickerComponent {
onChange(_: Date | null): void {}
@ViewChild(NzTimePickerComponent, { static: false }) nzTimePickerComponent!: NzTimePickerComponent;
}

@Component({
template: ` <nz-time-picker [nzStatus]="status"></nz-time-picker> `
})
export class NzTestTimePickerStatusComponent {
status: NzStatus = 'error';
}

@Component({
template: ` <div [dir]="dir"><nz-time-picker></nz-time-picker></div> `
})
export class NzTestTimePickerDirComponent {
dir: Direction = 'ltr';
}
26 changes: 23 additions & 3 deletions components/time-picker/time-picker.component.ts
Expand Up @@ -34,8 +34,8 @@ import { isValid } from 'date-fns';
import { slideMotion } from 'ng-zorro-antd/core/animation';
import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config';
import { warn } from 'ng-zorro-antd/core/logger';
import { BooleanInput, NzSafeAny } from 'ng-zorro-antd/core/types';
import { InputBoolean, isNil } from 'ng-zorro-antd/core/util';
import { BooleanInput, NgClassInterface, NzSafeAny, NzStatus } from 'ng-zorro-antd/core/types';
import { getStatusClassNames, InputBoolean, isNil } from 'ng-zorro-antd/core/util';
import { DateHelperService, NzI18nInterface, NzI18nService } from 'ng-zorro-antd/i18n';

const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'timePicker';
Expand Down Expand Up @@ -176,10 +176,15 @@ export class NzTimePickerComponent implements ControlValueAccessor, OnInit, Afte
}
] as ConnectionPositionPair[];
dir: Direction = 'ltr';
// status
prefixCls: string = 'ant-picker';
statusCls: NgClassInterface = {};
hasFeedback: boolean = false;

@ViewChild('inputElement', { static: true }) inputRef!: ElementRef<HTMLInputElement>;
@Input() nzId: string | null = null;
@Input() nzSize: string | null = null;
@Input() nzStatus?: NzStatus;
@Input() @WithConfig() nzHourStep: number = 1;
@Input() @WithConfig() nzMinuteStep: number = 1;
@Input() @WithConfig() nzSecondStep: number = 1;
Expand Down Expand Up @@ -347,7 +352,7 @@ export class NzTimePickerComponent implements ControlValueAccessor, OnInit, Afte
}

ngOnChanges(changes: SimpleChanges): void {
const { nzUse12Hours, nzFormat, nzDisabled, nzAutoFocus } = changes;
const { nzUse12Hours, nzFormat, nzDisabled, nzAutoFocus, nzStatus } = changes;
if (nzUse12Hours && !nzUse12Hours.previousValue && nzUse12Hours.currentValue && !nzFormat) {
this.nzFormat = 'h:mm:ss a';
}
Expand All @@ -363,6 +368,9 @@ export class NzTimePickerComponent implements ControlValueAccessor, OnInit, Afte
if (nzAutoFocus) {
this.updateAutoFocus();
}
if (nzStatus) {
this.setStatusStyles();
}
}

parseTimeString(str: string): void {
Expand Down Expand Up @@ -421,4 +429,16 @@ export class NzTimePickerComponent implements ControlValueAccessor, OnInit, Afte
disabledSeconds?.includes(value.getSeconds())
);
}

private setStatusStyles(): void {
// render status if nzStatus is set
this.statusCls = getStatusClassNames(this.prefixCls, this.nzStatus, this.hasFeedback);
Object.keys(this.statusCls).forEach(status => {
if (this.statusCls[status]) {
this.renderer.addClass(this.element.nativeElement, status);
} else {
this.renderer.removeClass(this.element.nativeElement, status);
}
});
}
}

0 comments on commit 0d8249b

Please sign in to comment.