From 44b7fe0e1f8892a2da9e9950da40081bab767d4d Mon Sep 17 00:00:00 2001 From: simplejason Date: Tue, 31 May 2022 10:26:39 +0800 Subject: [PATCH] feat(module:select): support setting status (#7478) * feat(module:select): support setting status * feat(module:select): add tests --- components/select/demo/module | 3 ++- components/select/demo/status.md | 15 +++++++++++ components/select/demo/status.ts | 12 +++++++++ components/select/doc/index.en-US.md | 1 + components/select/doc/index.zh-CN.md | 1 + components/select/select.component.ts | 36 +++++++++++++++++++++++--- components/select/select.spec.ts | 37 ++++++++++++++++++++++++++- 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 components/select/demo/status.md create mode 100644 components/select/demo/status.ts diff --git a/components/select/demo/module b/components/select/demo/module index a40e654501..b50b85b4e1 100644 --- a/components/select/demo/module +++ b/components/select/demo/module @@ -6,5 +6,6 @@ import { NzSpinModule } from 'ng-zorro-antd/spin'; import { NzInputModule } from 'ng-zorro-antd/input'; import { FormsModule } from '@angular/forms'; import { HttpClientJsonpModule } from '@angular/common/http'; +import { NzSpaceModule } from 'ng-zorro-antd/space'; -export const moduleList = [ FormsModule, NzSpinModule, HttpClientJsonpModule, NzSelectModule, NzDividerModule, NzRadioModule, NzIconModule, NzInputModule ]; +export const moduleList = [ FormsModule, NzSpinModule, HttpClientJsonpModule, NzSelectModule, NzDividerModule, NzRadioModule, NzIconModule, NzInputModule, NzSpaceModule ]; diff --git a/components/select/demo/status.md b/components/select/demo/status.md new file mode 100644 index 0000000000..e62885a550 --- /dev/null +++ b/components/select/demo/status.md @@ -0,0 +1,15 @@ +--- +order: 24 +title: + zh-CN: 自定义状态 + en-US: Status +--- + +## zh-CN + +使用 `nzStatus` 为 Select 添加状态,可选 `error` 或者 `warning`。 + +## en-US + +Add status to Select with `nzStatus`, which could be `error` or `warning`. + diff --git a/components/select/demo/status.ts b/components/select/demo/status.ts new file mode 100644 index 0000000000..ad23ed0156 --- /dev/null +++ b/components/select/demo/status.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-select-status', + template: ` + + + + + ` +}) +export class NzDemoSelectStatusComponent {} diff --git a/components/select/doc/index.en-US.md b/components/select/doc/index.en-US.md index 7fc58f4815..6fb7f61d89 100644 --- a/components/select/doc/index.en-US.md +++ b/components/select/doc/index.en-US.md @@ -51,6 +51,7 @@ import { NzSelectModule } from 'ng-zorro-antd/select'; | `[nzShowArrow]` | Whether to show the drop-down arrow | `boolean` | `true`(for single select), `false`(for multiple select) | | `[nzShowSearch]` | Whether show search input in single mode. | `boolean` | `false` | | `[nzSize]` | Size of Select input | `'large' \| 'small' \| 'default'` | `'default'` | +| `[nzStatus]` | Set validation status | `'error' \| 'warning'` | - | | `[nzSuffixIcon]` | The custom suffix icon | `TemplateRef \| string` | - | ✅ | | `[nzRemoveIcon]` | The custom remove icon | `TemplateRef` | - | | `[nzClearIcon]` | The custom clear icon | `TemplateRef` | - | diff --git a/components/select/doc/index.zh-CN.md b/components/select/doc/index.zh-CN.md index 187a3e089c..de168777a4 100644 --- a/components/select/doc/index.zh-CN.md +++ b/components/select/doc/index.zh-CN.md @@ -52,6 +52,7 @@ import { NzSelectModule } from 'ng-zorro-antd/select'; | `[nzShowArrow]` | 是否显示下拉小箭头 | `boolean` | 单选为 `true`,多选为 `false` | | `[nzShowSearch]` | 使单选模式可搜索 | `boolean` | `false` | | `[nzSize]` | 选择框大小 | `'large' \| 'small' \| 'default'` | `'default'` | +| `[nzStatus]` | 设置校验状态 | `'error' \| 'warning'` | - | | `[nzSuffixIcon]` | 自定义的选择框后缀图标 | `TemplateRef \| string` | - | ✅ | | `[nzRemoveIcon]` | 自定义的多选框清除图标 | `TemplateRef` | - | | `[nzClearIcon]` | 自定义的多选框清空图标 | `TemplateRef` | - | diff --git a/components/select/select.component.ts b/components/select/select.component.ts index 4540409ee7..fba46f434c 100644 --- a/components/select/select.component.ts +++ b/components/select/select.component.ts @@ -26,6 +26,7 @@ import { Optional, Output, QueryList, + Renderer2, SimpleChanges, TemplateRef, ViewChild, @@ -40,8 +41,15 @@ import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/con import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation'; import { cancelRequestAnimationFrame, reqAnimFrame } from 'ng-zorro-antd/core/polyfill'; import { NzDestroyService } from 'ng-zorro-antd/core/services'; -import { BooleanInput, NzSafeAny, OnChangeType, OnTouchedType } from 'ng-zorro-antd/core/types'; -import { InputBoolean, isNotNil } from 'ng-zorro-antd/core/util'; +import { + BooleanInput, + NgClassInterface, + NzSafeAny, + NzStatus, + OnChangeType, + OnTouchedType +} from 'ng-zorro-antd/core/types'; +import { getStatusClassNames, InputBoolean, isNotNil } from 'ng-zorro-antd/core/util'; import { NzOptionGroupComponent } from './option-group.component'; import { NzOptionComponent } from './option.component'; @@ -179,6 +187,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon @Input() nzId: string | null = null; @Input() nzSize: NzSelectSizeType = 'default'; + @Input() nzStatus?: NzStatus; @Input() nzOptionHeightPx = 32; @Input() nzOptionOverflowSize = 8; @Input() nzDropdownClassName: string | null = null; @@ -254,6 +263,11 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon focused = false; dir: Direction = 'ltr'; + // status + prefixCls: string = 'ant-select'; + statusCls: NgClassInterface = {}; + hasFeedback: boolean = false; + generateTagItem(value: string): NzSelectItemInterface { return { nzValue: value, @@ -508,6 +522,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon public nzConfigService: NzConfigService, private cdr: ChangeDetectorRef, private host: ElementRef, + private renderer: Renderer2, private platform: Platform, private focusMonitor: FocusMonitor, @Optional() private directionality: Directionality, @@ -551,7 +566,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon } ngOnChanges(changes: SimpleChanges): void { - const { nzOpen, nzDisabled, nzOptions } = changes; + const { nzOpen, nzDisabled, nzOptions, nzStatus } = changes; if (nzOpen) { this.onOpenChange(); } @@ -576,6 +591,9 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon }); this.listOfTemplateItem$.next(listOfTransformedItem); } + if (nzStatus) { + this.setStatusStyles(); + } } ngOnInit(): void { @@ -695,4 +713,16 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterCon cancelRequestAnimationFrame(this.requestId); this.focusMonitor.stopMonitoring(this.host); } + + 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.host.nativeElement, status); + } else { + this.renderer.removeClass(this.host.nativeElement, status); + } + }); + } } diff --git a/components/select/select.spec.ts b/components/select/select.spec.ts index 3754913788..cee48a71fa 100644 --- a/components/select/select.spec.ts +++ b/components/select/select.spec.ts @@ -12,7 +12,7 @@ import { ɵComponentBed as ComponentBed, ɵcreateComponentBed as createComponentBed } from 'ng-zorro-antd/core/testing'; -import { NzSafeAny } from 'ng-zorro-antd/core/types'; +import { NzSafeAny, NzStatus } from 'ng-zorro-antd/core/types'; import { NzIconTestModule } from 'ng-zorro-antd/icon/testing'; import { NzSelectSearchComponent } from './select-search.component'; @@ -1268,6 +1268,34 @@ describe('select', () => { expect(appRef.tick).toHaveBeenCalledTimes(0); }); }); + describe('status', () => { + let testBed: ComponentBed; + let component: TestSelectStatusComponent; + let fixture: ComponentFixture; + let selectElement!: HTMLElement; + + beforeEach(() => { + testBed = createComponentBed(TestSelectStatusComponent, { + imports: [NzSelectModule, NzIconTestModule] + }); + component = testBed.component; + fixture = testBed.fixture; + selectElement = testBed.debugElement.query(By.directive(NzSelectComponent)).nativeElement; + }); + + it('should classname correct', () => { + fixture.detectChanges(); + expect(selectElement.classList).toContain('ant-select-status-error'); + + component.status = 'warning'; + fixture.detectChanges(); + expect(selectElement.classList).toContain('ant-select-status-warning'); + + component.status = ''; + fixture.detectChanges(); + expect(selectElement.classList).not.toContain('ant-select-status-warning'); + }); + }); }); @Component({ @@ -1558,3 +1586,10 @@ export class TestSelectReactiveTagsComponent { nzTokenSeparators: string[] = []; nzMaxTagPlaceholder?: TemplateRef<{ $implicit: NzSafeAny[] }>; } + +@Component({ + template: ` ` +}) +export class TestSelectStatusComponent { + status: NzStatus = 'error'; +}