Skip to content

Commit

Permalink
chore(module:icon): remove old api (NG-ZORRO#4375)
Browse files Browse the repository at this point in the history
* feat(module:icon): remove old api

* fix(module:icon): remove duplicated constructor

BREAKING CHANGE: 


- `i[nz-icon]`:  `twoToneColor` `theme` `spin` `iconfont` `type` inputs has been removed, use `nzTwoToneColor` `nzTheme` `nzSpin` `nzIconfont` `nzType` instead.
- `i.anticon` selector has been removed, use `i[nz-icon]` instead.
  • Loading branch information
Wendell authored and Ricbet committed Apr 9, 2020
1 parent b10c87b commit 5a09a25
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 285 deletions.
2 changes: 0 additions & 2 deletions components/icon/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import { NzIconModule } from 'ng-zorro-antd/icon';
| `[nzIconfont]` | Type of the icon from iconfont | `string` | - |
| `[nzRotate]` | Rotate degrees | `number` | - |

<blockquote style="border-color: red;"><p><strong>API that is not started with nz and old API that is based on icon class names would be deprecated in 9.0.0. Please migrate.</strong></p></blockquote>

### NzIconService

| Methods/Properties | Description | Parameters |
Expand Down
2 changes: 0 additions & 2 deletions components/icon/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ import { NzIconModule } from 'ng-zorro-antd/icon';
| `[nzIconfont]` | 指定来自 IconFont 的图标类型 | string | - |
| `[nzRotate]` | 图标旋转角度(7.0.0 开始支持) | `number` | - |

<blockquote style="border-color: red;"><p><strong>不加上 nz 前缀的 API,以及原使用 icon 类名的 API 将会在 9.0.0 及之后不被支持,请及时迁移。</strong></p></blockquote>

### NzIconService

| 方法/属性 | 说明 | 参数 |
Expand Down
266 changes: 77 additions & 189 deletions components/icon/nz-icon.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,20 @@
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { Platform } from '@angular/cdk/platform';
import {
AfterContentChecked,
Directive,
ElementRef,
Input,
OnChanges,
OnDestroy,
OnInit,
Renderer2,
SimpleChanges
} from '@angular/core';
import { IconDirective, ThemeType } from '@ant-design/icons-angular';
import { warnDeprecation, InputBoolean } from 'ng-zorro-antd/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { NzIconService } from './nz-icon.service';

const iconTypeRE = /^anticon\-\w/;

const getIconTypeClass = (className: string): { name: string; index: number } | undefined => {
if (!className) {
return undefined;
} else {
const classArr = className.split(/\s/);
const index = classArr.findIndex(cls => cls !== 'anticon' && cls !== 'anticon-spin' && !!cls.match(iconTypeRE));
return index === -1 ? undefined : { name: classArr[index], index };
}
};
import { InputBoolean, NzUpdateHostClassService } from 'ng-zorro-antd/core';

const normalizeType = (rawType: string): { type: string; crossError: boolean; verticalError: boolean } => {
const ret = { type: rawType, crossError: false, verticalError: false };
ret.type = rawType ? rawType.replace('anticon-', '') : '';
if (ret.type.includes('verticle')) {
ret.type = 'up';
ret.verticalError = true;
}
if (ret.type.startsWith('cross')) {
ret.type = 'close';
ret.crossError = true;
}
return ret;
};
import { NzIconService } from './nz-icon.service';

/**
* This directive extends IconDirective to provide:
Expand All @@ -63,10 +34,14 @@ const normalizeType = (rawType: string): { type: string; crossError: boolean; ve
* - properties that not started with `nz`.
*/
@Directive({
selector: 'i.anticon, [nz-icon]',
exportAs: 'nzIcon'
selector: '[nz-icon]',
exportAs: 'nzIcon',
providers: [NzUpdateHostClassService],
host: {
'[class.anticon]': 'true'
}
})
export class NzIconDirective extends IconDirective implements OnInit, OnChanges, OnDestroy, AfterContentChecked {
export class NzIconDirective extends IconDirective implements OnInit, OnChanges, AfterContentChecked {
@Input()
@InputBoolean()
set nzSpin(value: boolean) {
Expand All @@ -75,86 +50,97 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,

@Input() nzRotate: number = 0;

@Input() set nzType(value: string) {
@Input()
set nzType(value: string) {
this.type = value;
}

@Input() set nzTheme(value: ThemeType) {
@Input()
set nzTheme(value: ThemeType) {
this.theme = value;
}

@Input() set nzTwotoneColor(value: string) {
@Input()
set nzTwotoneColor(value: string) {
this.twoToneColor = value;
}

@Input() set nzIconfont(value: string) {
@Input()
set nzIconfont(value: string) {
this.iconfont = value;
}

/** @deprecated 8.0.0 avoid exposing low layer API. */
@Input() spin = false;
private readonly el: HTMLElement;

/** @deprecated 8.0.0 avoid exposing low layer API. */
@Input() iconfont: string;
type: string;
theme: ThemeType;
// @ts-ignore
twotoneColor: string;

@Input()
set type(value: string) {
if (value && value.startsWith('anticon')) {
const rawClass = getIconTypeClass(value);
const type = rawClass ? normalizeType(rawClass.name).type : '';
if (type && this.type !== type) {
this._type = type;
}
private iconfont: string;
private spin: boolean = false;

constructor(
elementRef: ElementRef,
public iconService: NzIconService,
public renderer: Renderer2,
private nzUpdateHostClassService: NzUpdateHostClassService
) {
super(iconService, elementRef, renderer);

this.el = elementRef.nativeElement;
}

ngOnChanges(changes: SimpleChanges): void {
const { nzType, nzTwotoneColor, nzSpin, nzTheme, nzRotate } = changes;

if (nzType || nzTwotoneColor || nzSpin || nzTheme) {
this.changeIcon2();
} else if (nzRotate) {
this.handleRotate(this.el.firstChild as SVGElement);
} else {
this._type = value;
this._setSVGElement(this.iconService.createIconfontIcon(`#${this.iconfont}`));
}
}

get type(): string {
return this._type;
ngOnInit(): void {
this.renderer.setAttribute(this.el, 'class', `anticon ${this.el.className}`.trim());
}

private classNameObserver: MutationObserver;
private el = this.elementRef.nativeElement;
private destroy$ = new Subject<void>();
private _type: string;

/**
* Replacement of `changeIcon` for more modifications.
* @param oldAPI
* If custom content is provided, try to normalize SVG elements.
*/
private changeIcon2(oldAPI: boolean = false): void {
if (!oldAPI) {
this.setClassName();
}
this._changeIcon().then(svg => {
this.setSVGData(svg);
if (!oldAPI && svg) {
this.handleSpin(svg);
this.handleRotate(svg);
ngAfterContentChecked(): void {
if (!this.type) {
const children = this.el.children;
let length = children.length;
if (!this.type && children.length) {
while (length--) {
const child = children[length];
if (child.tagName.toLowerCase() === 'svg') {
this.iconService.normalizeSvgElement(child as SVGElement);
}
}
}
});
}
}

private classChangeHandler(className: string): void {
const ret = getIconTypeClass(className);
if (ret) {
const { type, crossError, verticalError } = normalizeType(ret.name);
if (crossError) {
this.iconService.warnAPI('cross');
}
if (verticalError) {
this.iconService.warnAPI('vertical');
}
if (this.type !== type) {
this._type = type;
this.changeIcon2(true);
/**
* Replacement of `changeIcon` for more modifications.
*/
private changeIcon2(): void {
this.setClassName();
this._changeIcon().then(svgOrRemove => {
if (svgOrRemove) {
this.setSVGData(svgOrRemove);
this.handleSpin(svgOrRemove);
this.handleRotate(svgOrRemove);
}
}
});
}

private handleSpin(svg: SVGElement): void {
if ((this.spin || this.type === 'loading') && !this.elementRef.nativeElement.classList.contains('anticon-spin')) {
if (this.spin || this.type === 'loading') {
this.renderer.addClass(svg, 'anticon-spin');
} else {
this.renderer.removeClass(svg, 'anticon-spin');
Expand All @@ -170,111 +156,13 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
}

private setClassName(): void {
if (typeof this.type === 'string') {
const iconClassNameArr = this.el.className.split(/\s/);
const ret = getIconTypeClass(this.el.className);
if (ret) {
iconClassNameArr.splice(ret.index, 1, `anticon-${this.type}`);
this.renderer.setAttribute(this.el, 'class', iconClassNameArr.join(' '));
} else {
this.renderer.addClass(this.el, `anticon-${this.type}`);
}
}
}

private setSVGData(svg: SVGElement | null): void {
if (typeof this.type === 'string' && svg) {
this.renderer.setAttribute(svg, 'data-icon', this.type);
this.renderer.setAttribute(svg, 'aria-hidden', 'true');
}
}

constructor(
public iconService: NzIconService,
public elementRef: ElementRef,
public renderer: Renderer2,
private platform: Platform
) {
super(iconService, elementRef, renderer);
}

ngOnChanges(changes: SimpleChanges): void {
const { type, nzType, nzTwotoneColor, twoToneColor, spin, nzSpin, theme, nzTheme, nzRotate } = changes;

if (type && !nzType) {
warnDeprecation(
`APIs for Icon without 'nz' prefix are deprecated and will be removed in 9.0.0! Please check icons with this type: '${type.currentValue}'.`
);
}

if (type || nzType || nzTwotoneColor || twoToneColor || spin || nzSpin || theme || nzTheme) {
this.changeIcon2();
} else if (nzRotate) {
this.handleRotate(this.el.firstChild);
} else {
this._setSVGElement(this.iconService.createIconfontIcon(`#${this.iconfont}`));
}

if (type && !nzType) {
warnDeprecation(
`APIs for Icon without 'nz' prefix are deprecated and will be removed in 9.0.0! Please check icons with this type: '${this.type}'.`
);
}
}

ngOnInit(): void {
// If `this.type` is not specified and `classList` contains `anticon`, it should be an icon using old API.
if (!this.type && this.el.classList.contains('anticon')) {
this.iconService.warnAPI('old');
// Get `type` from `className`. If not, initial rendering would be missed.
this.classChangeHandler(this.el.className);
if (this.platform.isBrowser) {
// Add `class` mutation observer.
this.classNameObserver = new MutationObserver((mutations: MutationRecord[]) => {
mutations
.filter((mutation: MutationRecord) => mutation.attributeName === 'class')
.forEach((mutation: MutationRecord) => this.classChangeHandler((mutation.target as HTMLElement).className));
});
this.classNameObserver.observe(this.el, { attributes: true });
}
}
// If `classList` does not contain `anticon`, add it before other class names.
if (!this.el.classList.contains('anticon')) {
this.renderer.setAttribute(this.el, 'class', `anticon ${this.el.className}`.trim());
}

this.iconService.configUpdated$
.asObservable()
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
if (this.type) {
this.changeIcon2();
}
});
}

ngOnDestroy(): void {
if (this.classNameObserver) {
this.classNameObserver.disconnect();
}

this.destroy$.next();
this.destroy$.complete();
this.nzUpdateHostClassService.updateHostClass(this.el, {
[`anticon-${this.type}`]: true
});
}

/**
* If custom content is provided, try to normalize SVG elements.
*/
ngAfterContentChecked(): void {
const children = this.el.children;
let length = children.length;
if (!this.type && children.length) {
while (length--) {
const child = children[length];
if (child.tagName.toLowerCase() === 'svg') {
this.iconService.normalizeSvgElement(child as SVGElement);
}
}
}
private setSVGData(svg: SVGElement): void {
this.renderer.setAttribute(svg, 'data-icon', this.type);
this.renderer.setAttribute(svg, 'aria-hidden', 'true');
}
}
16 changes: 1 addition & 15 deletions components/icon/nz-icon.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,6 @@ export class NzIconService extends IconService {

private iconfontCache = new Set<string>();

warnAPI(type: 'old' | 'cross' | 'vertical'): void {
if (type === 'old') {
warnDeprecation(
`'<i class="anticon"></i>' would be deprecated in 9.0.0. Please use '<i nz-icon nzType=""></i>' API. Please refer https://ng.ant.design/components/icon/en.`
);
}
if (type === 'cross') {
warnDeprecation(`'cross' icon is replaced by 'close' icon. This auto correction would be removed in 9.0.0.`);
}
if (type === 'vertical') {
warnDeprecation(`'verticle' is misspelled. Please use 'vertical'. This misspell would be fixed in 9.0.0.`);
}
}

normalizeSvgElement(svg: SVGElement): void {
if (!svg.getAttribute('viewBox')) {
this._renderer.setAttribute(svg, 'viewBox', '0 0 1024 1024');
Expand Down Expand Up @@ -177,8 +163,8 @@ export class NzIconService extends IconService {
`'NZ_ICON_DEFAULT_TWOTONE_COLOR' is deprecated and will be removed in 9.0.0. Please use 'NZ_CONFIG' instead!`
);
}
this.configDefaultTwotoneColor();

this.configDefaultTwotoneColor();
this.configDefaultTheme();
}

Expand Down
Loading

0 comments on commit 5a09a25

Please sign in to comment.