Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 426afa0

Browse files
feat(material/icon): add default options (#23638)
closes #23548
1 parent 3d2aefb commit 426afa0

File tree

3 files changed

+120
-5
lines changed

3 files changed

+120
-5
lines changed

‎src/material/icon/icon.spec.ts

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
HttpTestingController,
66
TestRequest,
77
} from '@angular/common/http/testing';
8-
import {Component, ErrorHandler, ViewChild} from '@angular/core';
9-
import {MatIconModule, MAT_ICON_LOCATION} from './index';
8+
import {Component, ErrorHandler, Provider,Type,ViewChild} from '@angular/core';
9+
import {MAT_ICON_DEFAULT_OPTIONS, MAT_ICON_LOCATION,MatIconModule} from './index';
1010
import {MatIconRegistry, getMatIconNoHttpProviderError} from './icon-registry';
1111
import {FAKE_SVGS} from './fake-svgs';
1212
import {wrappedErrorMessage} from '../../cdk/testing/private';
@@ -41,6 +41,19 @@ function verifyPathChildElement(element: Element, attributeValue: string): void
4141
expect(pathElement.getAttribute('name')).toBe(attributeValue);
4242
}
4343

44+
/** Creates a test component fixture. */
45+
function createComponent<T>(component: Type<T>, providers: Provider[] = []) {
46+
TestBed.configureTestingModule({
47+
imports: [MatIconModule],
48+
declarations: [component],
49+
providers: [...providers],
50+
});
51+
52+
TestBed.compileComponents();
53+
54+
return TestBed.createComponent<T>(component);
55+
}
56+
4457
describe('MatIcon', () => {
4558
let fakePath: string;
4659
let errorHandler: jasmine.SpyObj<ErrorHandler>;
@@ -1237,6 +1250,71 @@ describe('MatIcon without HttpClientModule', () => {
12371250
});
12381251
});
12391252

1253+
describe('MatIcon with default options', () => {
1254+
it('should be able to configure color globally', fakeAsync(() => {
1255+
const fixture = createComponent(IconWithLigature, [
1256+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {color: 'accent'}},
1257+
]);
1258+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1259+
fixture.detectChanges();
1260+
expect(iconElement.classList).not.toContain('mat-icon-no-color');
1261+
expect(iconElement.classList).toContain('mat-accent');
1262+
}));
1263+
1264+
it('should use passed color rather then color provided', fakeAsync(() => {
1265+
const fixture = createComponent(IconWithColor, [
1266+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {color: 'warn'}},
1267+
]);
1268+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1269+
fixture.detectChanges();
1270+
expect(iconElement.classList).not.toContain('mat-warn');
1271+
expect(iconElement.classList).toContain('mat-primary');
1272+
}));
1273+
1274+
it('should use default color if no color passed', fakeAsync(() => {
1275+
const fixture = createComponent(IconWithColor, [
1276+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {color: 'accent'}},
1277+
]);
1278+
const component = fixture.componentInstance;
1279+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1280+
component.iconColor = '';
1281+
fixture.detectChanges();
1282+
expect(iconElement.classList).not.toContain('mat-icon-no-color');
1283+
expect(iconElement.classList).not.toContain('mat-primary');
1284+
expect(iconElement.classList).toContain('mat-accent');
1285+
}));
1286+
1287+
it('should be able to configure font set globally', fakeAsync(() => {
1288+
const fixture = createComponent(IconWithLigature, [
1289+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {fontSet: 'custom-font-set'}},
1290+
]);
1291+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1292+
fixture.detectChanges();
1293+
expect(iconElement.classList).toContain('custom-font-set');
1294+
}));
1295+
1296+
it('should use passed fontSet rather then default one', fakeAsync(() => {
1297+
const fixture = createComponent(IconWithCustomFontCss, [
1298+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {fontSet: 'default-font-set'}},
1299+
]);
1300+
const component = fixture.componentInstance;
1301+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1302+
component.fontSet = 'custom-font-set';
1303+
fixture.detectChanges();
1304+
expect(iconElement.classList).not.toContain('default-font-set');
1305+
expect(iconElement.classList).toContain('custom-font-set');
1306+
}));
1307+
1308+
it('should use passed empty fontSet rather then default one', fakeAsync(() => {
1309+
const fixture = createComponent(IconWithCustomFontCss, [
1310+
{provide: MAT_ICON_DEFAULT_OPTIONS, useValue: {fontSet: 'default-font-set'}},
1311+
]);
1312+
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
1313+
fixture.detectChanges();
1314+
expect(iconElement.classList).not.toContain('default-font-set');
1315+
}));
1316+
});
1317+
12401318
@Component({template: `<mat-icon>{{iconName}}</mat-icon>`})
12411319
class IconWithLigature {
12421320
iconName = '';

‎src/material/icon/icon.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ import {
2121
Input,
2222
OnDestroy,
2323
OnInit,
24+
Optional,
2425
ViewEncapsulation,
2526
} from '@angular/core';
26-
import {CanColor, mixinColor} from '@angular/material/core';
27+
import {CanColor, ThemePalette,mixinColor} from '@angular/material/core';
2728
import {Subscription} from 'rxjs';
2829
import {take} from 'rxjs/operators';
2930

@@ -37,6 +38,19 @@ const _MatIconBase = mixinColor(
3738
},
3839
);
3940

41+
/** Default options for `mat-icon`. */
42+
export interface MatIconDefaultOptions {
43+
/** Default color of the icon. */
44+
color?: ThemePalette;
45+
/** Font set that the icon is a part of. */
46+
fontSet?: string;
47+
}
48+
49+
/** Injection token to be used to override the default options for `mat-icon`. */
50+
export const MAT_ICON_DEFAULT_OPTIONS = new InjectionToken<MatIconDefaultOptions>(
51+
'MAT_ICON_DEFAULT_OPTIONS',
52+
);
53+
4054
/**
4155
* Injection token used to provide the current location to `MatIcon`.
4256
* Used to handle server-side rendering and to stub out during unit tests.
@@ -216,9 +230,22 @@ export class MatIcon extends _MatIconBase implements OnInit, AfterViewChecked, C
216230
@Attribute('aria-hidden') ariaHidden: string,
217231
@Inject(MAT_ICON_LOCATION) private _location: MatIconLocation,
218232
private readonly _errorHandler: ErrorHandler,
233+
@Optional()
234+
@Inject(MAT_ICON_DEFAULT_OPTIONS)
235+
defaults?: MatIconDefaultOptions,
219236
) {
220237
super(elementRef);
221238

239+
if (defaults) {
240+
if (defaults.color) {
241+
this.color = this.defaultColor = defaults.color;
242+
}
243+
244+
if (defaults.fontSet) {
245+
this.fontSet = defaults.fontSet;
246+
}
247+
}
248+
222249
// If the user has not explicitly set aria-hidden, mark the icon as hidden, as this is
223250
// the right thing to do for the majority of icon use-cases.
224251
if (!ariaHidden) {

‎tools/public_api_guard/material/icon.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { OnInit } from '@angular/core';
2222
import { Optional } from '@angular/core';
2323
import { SafeHtml } from '@angular/platform-browser';
2424
import { SafeResourceUrl } from '@angular/platform-browser';
25+
import { ThemePalette } from '@angular/material/core';
2526

2627
// @public
2728
export function getMatIconFailedToSanitizeLiteralError(literal: SafeHtml): Error;
@@ -54,6 +55,9 @@ export interface IconOptions {
5455
// @public
5556
export type IconResolver = (name: string, namespace: string) => SafeResourceUrl | SafeResourceUrlWithIconOptions | null;
5657

58+
// @public
59+
export const MAT_ICON_DEFAULT_OPTIONS: InjectionToken<MatIconDefaultOptions>;
60+
5761
// @public
5862
export const MAT_ICON_LOCATION: InjectionToken<MatIconLocation>;
5963

@@ -62,7 +66,7 @@ export function MAT_ICON_LOCATION_FACTORY(): MatIconLocation;
6266

6367
// @public
6468
export class MatIcon extends _MatIconBase implements OnInit, AfterViewChecked, CanColor, OnDestroy {
65-
constructor(elementRef: ElementRef<HTMLElement>, _iconRegistry: MatIconRegistry, ariaHidden: string, _location: MatIconLocation, _errorHandler: ErrorHandler);
69+
constructor(elementRef: ElementRef<HTMLElement>, _iconRegistry: MatIconRegistry, ariaHidden: string, _location: MatIconLocation, _errorHandler: ErrorHandler, defaults?:MatIconDefaultOptions);
6670
get fontIcon(): string;
6771
set fontIcon(value: string);
6872
get fontSet(): string;
@@ -86,7 +90,13 @@ export class MatIcon extends _MatIconBase implements OnInit, AfterViewChecked, C
8690
// (undocumented)
8791
static ɵcmp: i0.ɵɵComponentDeclaration<MatIcon, "mat-icon", ["matIcon"], { "color": "color"; "inline": "inline"; "svgIcon": "svgIcon"; "fontSet": "fontSet"; "fontIcon": "fontIcon"; }, {}, never, ["*"]>;
8892
// (undocumented)
89-
static ɵfac: i0.ɵɵFactoryDeclaration<MatIcon, [null, null, { attribute: "aria-hidden"; }, null, null]>;
93+
static ɵfac: i0.ɵɵFactoryDeclaration<MatIcon, [null, null, { attribute: "aria-hidden"; }, null, null, { optional: true; }]>;
94+
}
95+
96+
// @public
97+
export interface MatIconDefaultOptions {
98+
color?: ThemePalette;
99+
fontSet?: string;
90100
}
91101

92102
// @public

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /