Skip to content

Commit b22672d

Browse files
authored
feat(module:icon): add provideNzIcon and provideNzIconPatch API (#8650)
1 parent bef12e6 commit b22672d

File tree

12 files changed

+221
-96
lines changed

12 files changed

+221
-96
lines changed

components/icon/doc/index.en-US.md

+39-22
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ import { NzIconModule } from 'ng-zorro-antd/icon';
2121
### [nz-icon]:standalone
2222

2323
| Property | Description | Type | Default | Global Config |
24-
| ------------------ | ----------------------------------------------------------- | ------------------------------ | ----------- | ------------- |
24+
|--------------------|-------------------------------------------------------------|--------------------------------|-------------|---------------|
2525
| `[nzType]` | Type of the ant design icon | `string` | - |
26-
| `[nzTheme]` | Type of the ant design icon | `'fill'\|'outline'\|'twotone'` | `'outline'` ||
26+
| `[nzTheme]` | Type of the ant design icon | `'fill'\|'outline'\|'twotone'` | `'outline'` | |
2727
| `[nzSpin]` | Rotate icon with animation | `boolean` | `false` |
28-
| `[nzTwotoneColor]` | Only support the two-tone icon. Specific the primary color. | `string (hex color)` | - ||
28+
| `[nzTwotoneColor]` | Only support the two-tone icon. Specific the primary color. | `string (hex color)` | - | |
2929
| `[nzIconfont]` | Type of the icon from iconfont | `string` | - |
3030
| `[nzRotate]` | Rotate degrees | `number` | - |
3131

3232
### NzIconService
3333

3434
| Methods/Properties | Description | Parameters |
35-
| ---------------------- | ------------------------------------------------------------------------------------------------ | ------------------------ |
35+
|------------------------|--------------------------------------------------------------------------------------------------|--------------------------|
3636
| `addIcon()` | To import icons statically | `IconDefinition` |
3737
| `addIconLiteral()` | To statically import custom icons | `string`, `string (SVG)` |
3838
| `fetchFromIconfont()` | To get icon assets from fonticon | `NzIconfontOption` |
@@ -47,9 +47,9 @@ We synced to Ant Design and replaced font icons with svg icons which bring benef
4747
- Support multiple colors for icon.
4848
- No need to change built-in icons with overriding styles by providing more props in component.
4949

50-
You can join in [this dicussion of Ant Design](https://github.com/ant-design/ant-design/issues/10353).
50+
You can join in [this discussion of Ant Design](https://github.com/ant-design/ant-design/issues/10353).
5151

52-
NG-ZORRO hadn't provided an icon component. Instead, icon based on font files was provided. We make this new directive compatible to old API. If you make no changes to your existing code, old icons would be dynamically loaded as `outline` icons. But the best pratice is always to use `nz-icon` directive and specify the `theme` prop.
52+
NG-ZORRO hadn't provided an icon component. Instead, icon based on font files was provided. We make this new directive compatible to old API. If you make no changes to your existing code, old icons would be dynamically loaded as `outline`icons. But the best practice is always to use `nz-icon` directive and specify the `theme` prop.
5353

5454
```html
5555
<span nz-icon [nzType]="'star'" [nzTheme]="'fill'"></span>
@@ -74,7 +74,7 @@ import { NzIconModule } from 'ng-zorro-antd/icon';
7474
// Import what you need. RECOMMENDED. ✔️
7575
import { AccountBookFill, AlertFill, AlertOutline } from '@ant-design/icons-angular/icons';
7676

77-
const icons: IconDefinition[] = [ AccountBookFill, AlertOutline, AlertFill ];
77+
const icons: IconDefinition[] = [AccountBookFill, AlertOutline, AlertFill];
7878

7979
// Import all. NOT RECOMMENDED. ❌
8080
// import * as AllIcons from '@ant-design/icons-angular/icons';
@@ -85,28 +85,23 @@ const icons: IconDefinition[] = [ AccountBookFill, AlertOutline, AlertFill ];
8585
// const icons: IconDefinition[] = Object.keys(antDesignIcons).map(key => antDesignIcons[key])
8686

8787
@NgModule({
88-
declarations: [
89-
AppComponent
90-
],
91-
imports: [
92-
NzIconModule.forRoot(icons),
93-
]
94-
bootstrap: [ AppComponent ]
88+
declarations: [AppComponent],
89+
imports: [NzIconModule.forRoot(icons)],
90+
bootstrap: [AppComponent]
9591
})
9692
export class AppModule {}
9793
```
9894

99-
For standalone mode, you register icons in `app.config.ts` like this:
95+
For standalone mode, you can register icons in `app.config.ts` with `provideNzIcons` API:
10096

10197
```typescript
102-
import { importProvidersFrom } from '@angular/core';
98+
import { provideNzIcons } from 'ng-zorro-antd/icon';
10399

104100
export const appConfig = {
105-
providers: [importProvidersFrom(NzIconModule.forRoot(icons))]
101+
providers: [provideNzIcons(icons)]
106102
}
107103
```
108104

109-
110105
Actually this calls `addIcon` of `NzIconService`. Icons imported would be bundled into your `.js` files. Static loading would increase your bundle's size so we recommend use dynamic importing as much as you can.
111106

112107
> Icons used by `NG-ZORRO` itself are imported statically to increase loading speed. However, icons demonstrated on the official website are loaded dynamically.
@@ -136,6 +131,8 @@ Please call this in component's constructor or `AppInitService`.
136131
Sometimes, you want to import icons in lazy modules to avoid increasing the size of the main.js. You can use `NzIconModule.forChild`.
137132

138133
```typescript
134+
import { NzIconModule } from 'ng-zorro-antd/icon';
135+
139136
@NgModule({
140137
imports: [CommonModule, NzIconModule.forChild([QuestionOutline])]
141138
})
@@ -144,15 +141,35 @@ class ChildModule {}
144141

145142
When `ChildModule` get loaded, the icon QuestionOutline would be usable across the application.
146143

144+
For standalone mode, you can import icons in `providers` of the standalone component or router with `provideNzIconsPatch` API.
145+
146+
```typescript
147+
import { NzIconModule, provideNzIconsPatch } from 'ng-zorro-antd/icon';
148+
149+
// in xxx.component.ts
150+
@Component({
151+
standalone: true,
152+
imports: [NzIconModule],
153+
providers: [provideNzIconsPatch([QuestionOutline])]
154+
})
155+
class ChildComponent {}
156+
157+
// or in xxx.routes.ts
158+
const routes: Routes = [{
159+
path: '',
160+
providers: [provideNzIconsPatch([QuestionOutline])],
161+
}]
162+
```
163+
147164
### Set Default TwoTone Color
148165

149-
When using the two-tone icons, you provide a global configuration like `{ nzIcon: { nzTwotoneColor: 'xxx' } }` via `NzConfigService` or call corresponding `set` method to change two default twotone color.
166+
When using the two-tone icons, you provide a global configuration like `{ nzIcon: { nzTwotoneColor: 'xxx' } }`via `NzConfigService` or call corresponding `set` method to change to default twotone color.
150167

151168
### Custom Font Icon
152169

153170
We added a `fetchFromIconfont` method function to help developer using their own icons deployed at [iconfont.cn](http://iconfont.cn/) in a convenient way.
154171

155-
> This method is specified for iconfont.cn.
172+
> This method is specified for [iconfont.cn](http://iconfont.cn/).
156173
157174
```typescript
158175
this._iconService.fetchFromIconfont({
@@ -164,12 +181,12 @@ this._iconService.fetchFromIconfont({
164181
<span nz-icon [nzIconfont]="'icon-tuichu'"></span>
165182
```
166183

167-
It create a component that uses SVG sprites in essence.
184+
It creates a component that uses SVG sprites in essence.
168185

169186
The following option are available:
170187

171188
| Property | Description | Type | Default |
172-
| ----------- | ----------------------------------------- | -------- | ------- |
189+
|-------------|-------------------------------------------|----------|---------|
173190
| `scriptUrl` | The URL generated by iconfont.cn project. | `string` | - |
174191

175192
The property scriptUrl should be set to import the svg sprite symbols.

components/icon/doc/index.zh-CN.md

+27-11
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,20 @@ const icons: IconDefinition[] = [ AccountBookFill, AlertOutline, AlertFill ];
8686
// const icons: IconDefinition[] = Object.keys(antDesignIcons).map(key => antDesignIcons[key])
8787

8888
@NgModule({
89-
declarations: [
90-
AppComponent
91-
],
92-
imports: [
93-
NzIconModule.forRoot(icons)
94-
]
95-
bootstrap: [ AppComponent ]
89+
declarations: [AppComponent],
90+
imports: [NzIconModule.forRoot(icons)],
91+
bootstrap: [AppComponent]
9692
})
9793
export class AppModule {}
9894
```
9995

100-
在 standalone 模式下,你可以在 `app.config.ts` 中引入这些图标
96+
在 standalone 模式下,你可以在 `app.config.ts` 中使用 `provideNzIcons` 引入这些图标
10197

10298
```typescript
103-
import { importProvidersFrom } from '@angular/core';
99+
import { provideNzIcons } from 'ng-zorro-antd/icon';
104100

105101
export const appConfig = {
106-
providers: [importProvidersFrom(NzIconModule.forRoot(icons))]
102+
providers: [provideNzIcons(icons)]
107103
}
108104
```
109105

@@ -146,13 +142,33 @@ class ChildModule {}
146142

147143
当然,不要忘记在 `NZ_ICONS` 中删除该图标。
148144

145+
在 Standalone 模式下,你可以在懒加载的组件中或路由的 `providers` 中使用 `provideNzIconsPatch` 来补充图标:
146+
147+
```typescript
148+
import { NzIconModule, provideNzIconsPatch } from 'ng-zorro-antd/icon';
149+
150+
// 在 xxx.component.ts 中
151+
@Component({
152+
standalone: true,
153+
imports: [NzIconModule],
154+
providers: [provideNzIconsPatch([QuestionOutline])]
155+
})
156+
class ChildComponent {}
157+
158+
// 或 在 xxx.routes.ts 中
159+
const routes: Routes = [{
160+
path: '',
161+
providers: [provideNzIconsPatch([QuestionOutline])],
162+
}]
163+
```
164+
149165
### 双色图标主色
150166

151167
对于双色图标,可以通过提供全局配置 `{ nzIcon: { nzTwotoneColor: 'xxx' } }``NzConfigService` 的对应方法修改来全局设置图标主色。
152168

153169
### 自定义 font 图标
154170

155-
我们提供了一个 `fetchFromIconfont` 方法,方便开发者调用在 iconfont.cn 上自行管理的图标。
171+
我们提供了一个 `fetchFromIconfont` 方法,方便开发者调用在 [iconfont.cn](http://iconfont.cn/) 上自行管理的图标。
156172

157173
```typescript
158174
this._iconService.fetchFromIconfont({

components/icon/icon.module.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ModuleWithProviders, NgModule } from '@angular/core';
88
import { IconDefinition } from '@ant-design/icons-angular';
99

1010
import { NzIconDirective } from './icon.directive';
11-
import { NZ_ICONS, NZ_ICONS_PATCH, NzIconPatchService } from './icon.service';
11+
import { provideNzIcons, provideNzIconsPatch } from './provide-icons';
1212

1313
@NgModule({
1414
imports: [NzIconDirective],
@@ -18,25 +18,14 @@ export class NzIconModule {
1818
static forRoot(icons: IconDefinition[]): ModuleWithProviders<NzIconModule> {
1919
return {
2020
ngModule: NzIconModule,
21-
providers: [
22-
{
23-
provide: NZ_ICONS,
24-
useValue: icons
25-
}
26-
]
21+
providers: [provideNzIcons(icons)]
2722
};
2823
}
2924

3025
static forChild(icons: IconDefinition[]): ModuleWithProviders<NzIconModule> {
3126
return {
3227
ngModule: NzIconModule,
33-
providers: [
34-
NzIconPatchService,
35-
{
36-
provide: NZ_ICONS_PATCH,
37-
useValue: icons
38-
}
39-
]
28+
providers: [provideNzIconsPatch(icons)]
4029
};
4130
}
4231
}

components/icon/icon.spec.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, DebugElement, NgModule } from '@angular/core';
2-
import { ComponentFixture, fakeAsync, inject, tick, waitForAsync } from '@angular/core/testing';
2+
import { ComponentFixture, TestBed, fakeAsync, inject, tick, waitForAsync } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44

55
import {
@@ -18,6 +18,7 @@ import { ComponentBed, createComponentBed } from 'ng-zorro-antd/core/testing/com
1818
import { NzIconDirective } from './icon.directive';
1919
import { NzIconModule } from './icon.module';
2020
import { NzIconService, NZ_ICONS } from './icon.service';
21+
import { provideNzIcons, provideNzIconsPatch } from './provide-icons';
2122

2223
describe('nz-icon', () => {
2324
describe('basics', () => {
@@ -210,7 +211,7 @@ describe('nz-icon', () => {
210211
nzConfigService!.set('icon', { nzTwotoneColor: '#234567' });
211212
expect(icons[0].componentInstance.iconService.twoToneColor.primaryColor).toBe('#234567');
212213

213-
// Should ignore falsy value.
214+
// Should ignore invalid value.
214215
nzConfigService!.set('icon', { nzTwotoneColor: '234567' });
215216
expect(icons[0].componentInstance.iconService.twoToneColor.primaryColor).not.toBe('234567');
216217
expect(icons[0].componentInstance.iconService.twoToneColor.primaryColor).toBe('#1890ff');
@@ -236,6 +237,29 @@ describe('nz-icon', () => {
236237
expect(icons[1].nativeElement.classList.contains('anticon-question')).toBe(true);
237238
});
238239
});
240+
241+
describe('[standalone] injection on multi places with provideNzIcon', () => {
242+
let fixture: ComponentFixture<NzTestIconMultiInjectionStandaloneComponent>;
243+
let icons: DebugElement[];
244+
245+
beforeEach(() => {
246+
TestBed.configureTestingModule({
247+
imports: [NzTestIconMultiInjectionStandaloneComponent],
248+
providers: [provideNzIcons([HomeOutline])]
249+
}).compileComponents();
250+
});
251+
252+
beforeEach(() => {
253+
fixture = TestBed.createComponent(NzTestIconMultiInjectionStandaloneComponent);
254+
fixture.detectChanges();
255+
});
256+
257+
it('should support forRoot and forChild', () => {
258+
icons = fixture.debugElement.queryAll(By.directive(NzIconDirective));
259+
expect(icons[0].nativeElement.classList.contains('anticon-home')).toBe(true);
260+
expect(icons[1].nativeElement.classList.contains('anticon-question')).toBe(true);
261+
});
262+
});
239263
});
240264

241265
@Component({
@@ -297,3 +321,14 @@ class ChildModule {}
297321
`
298322
})
299323
class NzTestIconMultiInjectionComponent {}
324+
325+
@Component({
326+
standalone: true,
327+
imports: [NzIconModule],
328+
providers: [provideNzIconsPatch([QuestionOutline])],
329+
template: `
330+
<span nz-icon nzType="home"></span>
331+
<span nz-icon nzType="question"></span>
332+
`
333+
})
334+
class NzTestIconMultiInjectionStandaloneComponent {}

components/icon/provide-icons.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Use of this source code is governed by an MIT-style license that can be
3+
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
4+
*/
5+
6+
import { EnvironmentProviders, makeEnvironmentProviders, Provider } from '@angular/core';
7+
8+
import { IconDefinition } from '@ant-design/icons-angular';
9+
10+
import { NZ_ICONS, NZ_ICONS_PATCH, NzIconPatchService } from './icon.service';
11+
12+
/**
13+
* Provide icon definitions for NzIcon in root
14+
*
15+
* @param icons Icon definitions
16+
*/
17+
export const provideNzIcons = (icons: IconDefinition[]): EnvironmentProviders => {
18+
return makeEnvironmentProviders([
19+
{
20+
provide: NZ_ICONS,
21+
useValue: icons
22+
}
23+
]);
24+
};
25+
26+
/**
27+
* Provide icon definitions for NzIcon in feature module or standalone component
28+
*
29+
* @param icons Icon definitions
30+
*/
31+
export const provideNzIconsPatch = (icons: IconDefinition[]): Provider[] => {
32+
return [
33+
NzIconPatchService,
34+
{
35+
provide: NZ_ICONS_PATCH,
36+
useValue: icons
37+
}
38+
];
39+
};

components/icon/public-api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export * from './icon.module';
77
export * from './icon.directive';
88
export * from './icon.service';
99
export * from './icons';
10+
export * from './provide-icons';

0 commit comments

Comments
 (0)