Skip to content

Commit 8a0d412

Browse files
Wendellvthinkxie
Wendell
authored andcommitted
fix(module:icon): fix icons problems (#2325)
1 parent 46e8977 commit 8a0d412

16 files changed

+165
-104
lines changed

Diff for: components/button/nz-button.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ describe('button', () => {
167167
tick();
168168
fixture.detectChanges();
169169
expect(button.nativeElement.classList.contains('ant-btn-loading')).toBe(true);
170-
expect(button.nativeElement.firstElementChild.classList.contains('anticon-spin')).toBe(true);
170+
expect(button.nativeElement.firstElementChild.firstElementChild.classList.contains('anticon-spin')).toBe(true);
171171
expect(button.nativeElement.firstElementChild.classList.contains('anticon-loading')).toBe(true);
172172
expect(button.nativeElement.firstElementChild.localName).toBe('i');
173173
tick(5000);
@@ -179,15 +179,15 @@ describe('button', () => {
179179
const button = buttons[ 3 ];
180180
fixture.detectChanges();
181181
expect(button.nativeElement.classList.contains('ant-btn-loading')).toBe(false);
182-
expect(button.nativeElement.firstElementChild.classList.contains('anticon-apin')).toBe(false);
182+
expect(button.nativeElement.firstElementChild.querySelector('svg')).toBe(null);
183183
expect(button.nativeElement.firstElementChild.classList.contains('anticon-loading')).toBe(false);
184184
expect(button.nativeElement.firstElementChild.localName).toBe('i');
185185
button.nativeElement.click();
186186
fixture.detectChanges();
187187
tick();
188188
fixture.detectChanges();
189189
expect(button.nativeElement.classList.contains('ant-btn-loading')).toBe(true);
190-
expect(button.nativeElement.firstElementChild.classList.contains('anticon-spin')).toBe(true);
190+
expect(button.nativeElement.firstElementChild.firstElementChild.classList.contains('anticon-spin')).toBe(true);
191191
expect(button.nativeElement.firstElementChild.classList.contains('anticon-loading')).toBe(true);
192192
expect(button.nativeElement.firstElementChild.localName).toBe('i');
193193
tick(5000);

Diff for: components/cascader/nz-cascader.component.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -173,19 +173,20 @@ export class NzCascaderComponent implements OnInit, OnDestroy, ControlValueAcces
173173
if (!this.inSearch && willBeInSearch) {
174174
this.oldActivatedOptions = this.activatedOptions;
175175
this.activatedOptions = [];
176-
this.searchWidthStyle = `${this.input.nativeElement.offsetWidth}px`;
177176
} else if (this.inSearch && !willBeInSearch) {
178177
this.activatedOptions = this.oldActivatedOptions;
179178
}
180179

181180
// 搜索状态变更之后
182181
this.inSearch = !!willBeInSearch;
183182
if (this.inSearch) {
183+
this.labelRenderText = '';
184184
this.prepareSearchValue();
185185
} else {
186186
if (this.showSearch) {
187187
this.nzColumns = this.oldColumnsHolder;
188188
}
189+
this.buildDisplayLabel();
189190
this.searchWidthStyle = '';
190191
}
191192
this.setClassMap();

Diff for: components/cascader/nz-cascader.spec.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,9 @@ describe('cascader', () => {
13771377
it('should support custom sorter', (done) => {
13781378
testComponent.nzShowSearch = {
13791379
sorter(a: CascaderOption[], b: CascaderOption[], inputValue: string): number {
1380-
return 1; // all reversed, just to be sure it works
1380+
const l1 = a[ 0 ].label;
1381+
const l2 = b[ 0 ].label; // all reversed, just to be sure it works
1382+
return ('' + l1).localeCompare(l2);
13811383
}
13821384
} as NzShowSearchOptions;
13831385
fixture.detectChanges();

Diff for: components/form/nz-form-control.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<span class="ant-form-item-children">
33
<ng-content></ng-content>
44
<span class="ant-form-item-children-icon">
5-
<i *ngIf="nzHasFeedback" nz-icon [type]="iconType"></i>
5+
<i *ngIf="nzHasFeedback && iconType" nz-icon [type]="iconType"></i>
66
</span>
77
</span>
88
<ng-content select="nz-form-explain"></ng-content>

Diff for: components/icon/demo/basic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import { Component } from '@angular/core';
1818
<i class="anticon anticon-loading anticon-spin"></i>
1919
</div>
2020
`,
21-
styles: [ `
21+
styles : [ `
2222
.icons-list > .anticon {
2323
margin-right: 6px;
2424
font-size: 24px;
2525
}
26-
`]
26+
` ]
2727
})
2828
export class NzDemoIconBasicComponent {
2929
}

Diff for: components/icon/nz-icon.directive.ts

+85-43
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
import { IconDirective } from '@ant-design/icons-angular';
1313
import { NzIconService } from './nz-icon.service';
1414

15+
const iconTypeRE = /^anticon\-\w/;
16+
1517
/**
1618
* This directive extends IconDirective to provide:
1719
*
@@ -32,78 +34,113 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
3234

3335
/**
3436
* In order to make this directive compatible to old API, we had do some ugly stuff here.
35-
* Should be removed in next major version.
37+
* TODO: Should be removed in next major version.
3638
*/
3739
private _classChangeHandler(className: string): void {
38-
if (!className) { return; }
39-
40-
const forceSpin = className.indexOf('anticon-spin') > -1;
41-
const classArr = className.split(/\s/);
42-
let anticonType = classArr.filter(cls => cls !== 'anticon' && cls !== 'anticon-spin' && cls.match(/^anticon\-\w/))[ 0 ];
40+
if (className) {
41+
const iconType = className
42+
.split(/\s/)
43+
.filter(cls => cls !== 'anticon' && cls !== 'anticon-spin' && !!cls.match(iconTypeRE))[ 0 ];
4344

44-
if (!anticonType) { return; }
45+
if (!iconType) {
46+
return;
47+
}
4548

46-
anticonType = anticonType.replace('anticon-', '');
47-
if (anticonType.includes('verticle')) {
48-
anticonType = anticonType.replace('verticle', 'vertical');
49-
if (!this._iconService.warnedAboutVertical) {
50-
console.warn('[NG-ZORRO]', `'verticle' is misspelled, would be corrected in the next major version.`);
51-
this._iconService.warnedAboutVertical = true;
49+
let parsedIconType = iconType.replace('anticon-', '');
50+
if (parsedIconType.includes('verticle')) {
51+
parsedIconType = parsedIconType.replace('verticle', 'vertical');
52+
this._warnAPI('cross');
5253
}
53-
}
54-
if (anticonType.startsWith('cross')) {
55-
anticonType = anticonType.replace('cross', 'close');
56-
if (!this._iconService.warnedAboutCross) {
57-
console.warn('[NG-ZORRO]', `'cross' icon is replaced by 'close' icon.`);
58-
this._iconService.warnedAboutCross = true;
54+
if (parsedIconType.startsWith('cross')) {
55+
parsedIconType = parsedIconType.replace('cross', 'close');
56+
this._warnAPI('vertical');
5957
}
60-
}
61-
if (!(anticonType.endsWith('-o') || anticonType.endsWith('-fill') || anticonType.endsWith('-twotone'))) {
62-
anticonType += '-o';
63-
}
6458

65-
if (this.type !== anticonType) {
66-
this.type = anticonType;
67-
this._changeIcon().catch(err => {
59+
// Only change icon when icon type does change.
60+
if (this.type !== parsedIconType) {
61+
this.type = parsedIconType;
62+
this._changeIcon().catch(err => {
6863
console.warn('[NG-ZORRO]', `You can find more about this error on http://ng.ant.design/components/icon/en\n`, err);
6964
});
65+
}
7066
}
7167
}
7268

73-
private _warnAPI(): void {
74-
if (isDevMode() && !this._iconService.warnedAboutAPI) {
75-
console.warn('[NG-ZORRO]', `<i class="anticon"></i> would be deprecated soon. Please use <i nz-icon type=""></i> API.`);
69+
/**
70+
* In order to make this directive compatible to old API, we had do some ugly stuff here.
71+
* TODO: Should be removed in next major version.
72+
*/
73+
private _warnAPI(type: 'old' | 'cross' | 'vertical'): void {
74+
if (isDevMode()) {
75+
if (type === 'old' && !this._iconService.warnedAboutAPI) {
76+
console.warn('[NG-ZORRO]', `<i class="anticon"></i> would be deprecated soon. Please use <i nz-icon type=""></i> API.`);
77+
this._iconService.warnedAboutAPI = true;
78+
}
79+
if (type === 'cross' && !this._iconService.warnedAboutCross) {
80+
console.warn('[NG-ZORRO]', `'cross' icon is replaced by 'close' icon.`);
81+
this._iconService.warnedAboutCross = true;
82+
}
83+
if (type === 'vertical' && !this._iconService.warnedAboutVertical) {
84+
console.warn('[NG-ZORRO]', `'verticle' is misspelled, would be corrected in the next major version.`);
85+
this._iconService.warnedAboutVertical = true;
86+
}
7687
}
77-
this._iconService.warnedAboutAPI = true;
7888
}
7989

80-
private _addExtraModifications(svg: SVGElement): void {
81-
if (this.spin || this.type === 'loading') {
82-
this._renderer.addClass(this._el, 'anticon-spin');
90+
private _toggleSpin(svg: SVGElement): void {
91+
if ((this.spin || this.type === 'loading') && !this._el.classList.contains('anticon-spin')) {
92+
this._renderer.addClass(svg, 'anticon-spin');
8393
} else {
84-
this._renderer.removeClass(this._el, 'anticon-spin');
94+
this._renderer.removeClass(svg, 'anticon-spin');
95+
}
96+
}
97+
98+
private _setClassName(): void {
99+
// If there's not an anticon class, usually a new API icon, get the icon class name back.
100+
// anticon should be added before other class names.
101+
if (this._el && typeof this.type === 'string') {
102+
const iconClassNameArr = this._el.className.split(/\s/);
103+
const oldTypeNameIndex = iconClassNameArr.findIndex(cls => cls !== 'anticon' && cls !== 'anticon-spin' && !!cls.match(iconTypeRE));
104+
105+
if (oldTypeNameIndex !== -1) {
106+
iconClassNameArr.splice(oldTypeNameIndex, 1, `anticon-${this.type}`);
107+
this._renderer.setAttribute(this._el, 'class', iconClassNameArr.join(' '));
108+
} else {
109+
this._renderer.addClass(this._el, `anticon-${this.type}`);
110+
}
85111
}
86112
}
87113

88-
private _getIconNameBack(): void {
114+
private _setSVGData(svg: SVGElement): void {
89115
if (typeof this.type === 'string') {
90-
this._renderer.addClass(this._elementRef.nativeElement, `anticon-${this.type}`);
116+
this._renderer.setAttribute(svg, 'data-icon', this.type);
117+
this._renderer.setAttribute(svg, 'aria-hidden', 'true');
91118
}
92119
}
93120

121+
private _addExtraModifications(svg: SVGElement): void {
122+
this._toggleSpin(svg);
123+
this._setSVGData(svg);
124+
}
125+
94126
constructor(public _iconService: NzIconService, public _elementRef: ElementRef, public _renderer: Renderer2) {
95-
super(_iconService, _elementRef, _renderer); // NzIconService extends IconService so IconDirective won't complain.
127+
super(_iconService, _elementRef, _renderer);
96128
}
97129

98130
ngOnChanges(): void {
99131
if (!this.iconfont) {
100-
this._getIconNameBack(); // Should get back classNames immediately.
132+
// For ant design icons.
133+
this._setClassName();
101134
this._changeIcon().then(svg => {
102135
this._addExtraModifications(svg);
103-
}).catch(() => {
104-
console.warn('[NG-ZORRO]', `You can find more about this error on http://ng.ant.design/components/icon/en`);
136+
}).catch((err) => {
137+
if (err) {
138+
console.error(err);
139+
console.warn('[NG-ZORRO]', `You can find more about this error on http://ng.ant.design/components/icon/en`);
140+
}
105141
});
106142
} else {
143+
// For iconfont icons.
107144
this._setSVGElement(this._iconService.createIconfontIcon(`#${this.iconfont}`));
108145
}
109146
}
@@ -113,8 +150,10 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
113150
*/
114151
ngOnInit(): void {
115152
this._el = this._elementRef.nativeElement;
153+
154+
// Make the component compatible to old class="anticon" API.
116155
if (this._el && !this.type) {
117-
this._warnAPI();
156+
this._warnAPI('old');
118157
this._classChangeHandler(this._el.className);
119158
this._classNameObserver = new MutationObserver((mutations: MutationRecord[]) => {
120159
mutations
@@ -127,6 +166,10 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
127166
if (!this._el.classList.contains('anticon')) {
128167
this._renderer.setAttribute(this._el, 'class', `anticon ${this._el.className}`);
129168
}
169+
170+
if (this.type) {
171+
this._setClassName();
172+
}
130173
}
131174

132175
ngOnDestroy(): void {
@@ -141,8 +184,7 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
141184
ngAfterContentChecked(): void {
142185
const children = (this._elementRef.nativeElement as HTMLElement).children;
143186
if (children && children.length && !this.type) {
144-
const child = children[ 0 ];
145-
this._iconService.normalizeSvgElement(child as SVGElement);
187+
this._iconService.normalizeSvgElement(children[ 0 ] as SVGElement);
146188
}
147189
}
148190
}

Diff for: components/icon/nz-icon.service.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ export class NzIconService extends IconService {
6969
}
7070

7171
createIconfontIcon(type: string): SVGElement {
72-
const svgString = `<svg><use xlink:href="${type}"></svg>`;
73-
return this._createSVGElementFromString(svgString);
72+
return this._createSVGElementFromString(`<svg><use xlink:href="${type}"></svg>`);
7473
}
7574

7675
constructor(

Diff for: components/icon/nz-icon.spec.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,43 @@ describe('icon', () => {
2828

2929
it('should get icon class name back', fakeAsync(() => {
3030
fixture.detectChanges();
31-
expect(icons[ 0 ].nativeElement.classList.contains('anticon-question'));
32-
expect(icons[ 1 ].nativeElement.classList.contains('anticon-loading'));
31+
tick(1000);
32+
fixture.detectChanges();
33+
expect(icons[ 0 ].nativeElement.classList.contains('anticon')).toBe(true);
34+
expect(icons[ 0 ].nativeElement.classList.contains('anticon-question')).toBe(true);
35+
expect(icons[ 1 ].nativeElement.classList.contains('anticon-loading')).toBe(true);
36+
}));
37+
38+
it('should change class name when type changes', fakeAsync(() => {
39+
fixture.detectChanges();
40+
tick(1000);
41+
fixture.detectChanges();
42+
testComponent.type = 'question-circle';
43+
fixture.detectChanges();
44+
tick(1000);
45+
fixture.detectChanges();
46+
expect(icons[ 0 ].nativeElement.classList.contains('anticon')).toBe(true);
47+
expect(icons[ 0 ].nativeElement.classList.contains('anticon-question-circle')).toBe(true);
48+
expect(icons[ 0 ].nativeElement.classList.contains('anticon-question')).not.toBe(true);
3349
}));
3450

3551
it('should support spin and cancel', fakeAsync(() => {
3652
fixture.detectChanges();
3753
tick(1000);
3854
fixture.detectChanges();
39-
expect(icons[ 0 ].nativeElement.classList.contains('anticon-spin')).toBe(true);
55+
expect(icons[ 0 ].nativeElement.firstChild.classList.contains('anticon-spin')).toBe(true);
4056
testComponent.spin = false;
4157
fixture.detectChanges();
4258
tick(1000);
4359
fixture.detectChanges();
44-
expect(icons[ 0 ].nativeElement.classList.contains('anticon-spin')).toBe(false);
60+
expect(icons[ 0 ].nativeElement.firstChild.classList.contains('anticon-spin')).toBe(false);
4561
}));
4662

4763
it('should make loading spin', fakeAsync(() => {
4864
fixture.detectChanges();
4965
tick(1000);
5066
fixture.detectChanges();
51-
expect(icons[ 1 ].nativeElement.classList.contains('anticon-spin')).toBe(true);
67+
expect(icons[ 1 ].nativeElement.firstChild.classList.contains('anticon-spin')).toBe(true);
5268
}));
5369
});
5470

Diff for: components/layout/nz-layout.module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
22
import { NgModule } from '@angular/core';
33

44
import { NzMatchMediaService } from '../core/services/nz-match-media.service';
5+
import { NzIconModule } from '../icon/nz-icon.module';
56

67
import { NzContentComponent } from './nz-content.component';
78
import { NzFooterComponent } from './nz-footer.component';
@@ -13,7 +14,7 @@ import { NzSiderComponent } from './nz-sider.component';
1314
declarations: [ NzLayoutComponent, NzHeaderComponent, NzContentComponent, NzFooterComponent, NzSiderComponent ],
1415
exports : [ NzLayoutComponent, NzHeaderComponent, NzContentComponent, NzFooterComponent, NzSiderComponent ],
1516
providers : [ NzMatchMediaService ],
16-
imports : [ CommonModule ]
17+
imports : [ CommonModule, NzIconModule ]
1718
})
1819
export class NzLayoutModule {
1920
}

Diff for: components/layout/nz-sider.component.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
<ng-template [ngTemplateOutlet]="nzTrigger"></ng-template>
99
</div>
1010
<ng-template #defaultTrigger>
11-
<i class="anticon" [class.anticon-left]="!nzCollapsed" [class.anticon-right]="nzCollapsed" *ngIf="!nzReverseArrow"></i>
12-
<i class="anticon" [class.anticon-left]="nzCollapsed" [class.anticon-right]="!nzCollapsed" *ngIf="nzReverseArrow"></i>
11+
<i nz-icon [type]="nzCollapsed ? 'right' : 'left'" *ngIf="!nzReverseArrow"></i>
12+
<i nz-icon [type]="nzCollapsed ? 'left' : 'right'" *ngIf="nzReverseArrow"></i>
1313
</ng-template>

Diff for: components/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"dependencies": {
2424
"date-fns": "^1.29.0",
2525
"@angular/cdk": "^6.0.0",
26-
"@ant-design/icons-angular": "^0.0.2"
26+
"@ant-design/icons-angular": "^0.0.3"
2727
},
2828
"peerDependencies": {
2929
"@angular/animations": "^6.0.0",

Diff for: components/pagination/nz-pagination.component.html

+6-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@
3737
[class.mini]="nzSize=='small'"
3838
[class.ant-table-pagination]="nzInTable"
3939
class="ant-pagination">
40-
<span class="ant-pagination-total-text" *ngIf="nzShowTotal">
41-
<ng-template
42-
[ngTemplateOutlet]="nzShowTotal"
43-
[ngTemplateOutletContext]="{ $implicit: nzTotal,range:[(nzPageIndex-1)*nzPageSize+1, min(nzPageIndex*nzPageSize, nzTotal)] }">
44-
</ng-template>
45-
</span>
40+
<li class="ant-pagination-total-text" *ngIf="nzShowTotal">
41+
<ng-template
42+
[ngTemplateOutlet]="nzShowTotal"
43+
[ngTemplateOutletContext]="{ $implicit: nzTotal,range:[(nzPageIndex-1)*nzPageSize+1, min(nzPageIndex*nzPageSize, nzTotal)] }">
44+
</ng-template>
45+
</li>
4646
<li
4747
title="{{ locale.prev_page }}"
4848
class="ant-pagination-prev"

0 commit comments

Comments
 (0)