parent
bf956419ec
commit
3d45099070
|
@ -48,6 +48,7 @@ Take your icons to the next level with these advanced features.
|
|||
* [Layers](./usage/features.md#layers)
|
||||
* [Layers with text](./usage/features.md#layers-with-text)
|
||||
* [Layers with counter](./usage/features.md#layers-with-counter)
|
||||
* [Programmatic API](./usage/features.md#programmatic-api)
|
||||
|
||||
## Configurations
|
||||
* [Changing the Default Prefix](./usage/default-prefix.md)
|
||||
|
|
|
@ -175,3 +175,50 @@ The following features are available as part of Font Awesome. Note that the synt
|
|||
<fa-layers-counter content="99+"></fa-layers-counter>
|
||||
</fa-layers>
|
||||
```
|
||||
|
||||
### Programmatic API
|
||||
|
||||
To create `FaIconComponent` dynamically using `ComponentFactoryResolver`:
|
||||
|
||||
```ts
|
||||
@Component({
|
||||
selector: 'fa-host',
|
||||
template: '<ng-container #host></ng-container>'
|
||||
})
|
||||
class HostComponent {
|
||||
@ViewChild('host', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
|
||||
|
||||
constructor(private cfr: ComponentFactoryResolver) {
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
const factory = this.cfr.resolveComponentFactory(FaIconComponent);
|
||||
const componentRef = this.container.createComponent(factory);
|
||||
componentRef.instance.icon = faUser;
|
||||
// Note that FaIconComponent.render() should be called to update the
|
||||
// rendered SVG after setting/updating component inputs.
|
||||
componentRef.instance.render();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To update `FaIconComponent` programmatically:
|
||||
|
||||
```ts
|
||||
@Component({
|
||||
selector: 'fa-host',
|
||||
template: '<fa-icon [icon]="faUser" (click)="spinIcon()"></fa-icon>'
|
||||
})
|
||||
class HostComponent {
|
||||
faUser = faUser;
|
||||
|
||||
@ViewChild(FaIconComponent, {static: true}) iconComponent: FaIconComponent;
|
||||
|
||||
spinIcon() {
|
||||
this.iconComponent.spin = true;
|
||||
// Note that FaIconComponent.render() should be called to update the
|
||||
// rendered SVG after setting/updating component inputs.
|
||||
this.iconComponent.render();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -26,6 +26,10 @@ import { FaStackComponent } from './stack/stack.component';
|
|||
FaStackComponent,
|
||||
FaStackItemSizeDirective,
|
||||
],
|
||||
entryComponents: [
|
||||
FaIconComponent,
|
||||
FaDuotoneIconComponent,
|
||||
]
|
||||
})
|
||||
export class FontAwesomeModule {
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Component, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';
|
||||
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faDummy, initTest, queryByCss } from '../../testing/helpers';
|
||||
import { FaDuotoneIconComponent } from './duotone-icon.component';
|
||||
|
@ -104,4 +104,32 @@ describe('FaDuotoneIconComponent', () => {
|
|||
'or use: <fa-icon icon="user"></fa-icon> instead.'
|
||||
));
|
||||
});
|
||||
|
||||
it('should be able to create component dynamically', () => {
|
||||
@Component({
|
||||
selector: 'fa-host',
|
||||
template: '<ng-container #host></ng-container>'
|
||||
})
|
||||
class HostComponent {
|
||||
@ViewChild('host', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
|
||||
|
||||
constructor(private cfr: ComponentFactoryResolver) {
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
const factory = this.cfr.resolveComponentFactory(FaDuotoneIconComponent);
|
||||
const componentRef = this.container.createComponent(factory);
|
||||
componentRef.instance.icon = faDummy;
|
||||
componentRef.instance.render();
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = initTest(HostComponent);
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg')).toBeFalsy();
|
||||
|
||||
fixture.componentInstance.createIcon();
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,28 +1,13 @@
|
|||
import { Component, Type } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, inject } from '@angular/core/testing';
|
||||
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faUser as faUserRegular } from '@fortawesome/free-regular-svg-icons';
|
||||
import { Component, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';
|
||||
import { ComponentFixture, inject } from '@angular/core/testing';
|
||||
|
||||
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||
import { faUser as faUserRegular } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
||||
import { initTest, queryByCss } from '../../testing/helpers';
|
||||
import { FaIconComponent } from './icon.component';
|
||||
import { FaIconService } from './icon.service';
|
||||
|
||||
const iconServiceStub: FaIconService = {
|
||||
defaultPrefix: 'fas',
|
||||
};
|
||||
|
||||
function initTest<T>(component: Type<T>): ComponentFixture<T> {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ FaIconComponent, component ],
|
||||
providers: [ {provide: FaIconService, useValue: iconServiceStub } ]
|
||||
});
|
||||
return TestBed.createComponent(component);
|
||||
}
|
||||
|
||||
function svgIcon(fixture: ComponentFixture<any>): SVGElement {
|
||||
return fixture.debugElement.nativeElement.querySelector('svg');
|
||||
}
|
||||
|
||||
describe('FaIconComponent', () => {
|
||||
it('should render SVG icon', () => {
|
||||
@Component({
|
||||
|
@ -35,7 +20,7 @@ describe('FaIconComponent', () => {
|
|||
|
||||
const fixture = initTest(HostComponent);
|
||||
fixture.detectChanges();
|
||||
expect(svgIcon(fixture)).toBeTruthy();
|
||||
expect(queryByCss(fixture, 'svg')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support binding to boolean inputs', () => {
|
||||
|
@ -50,11 +35,60 @@ describe('FaIconComponent', () => {
|
|||
|
||||
const fixture = initTest(HostComponent);
|
||||
fixture.detectChanges();
|
||||
expect(svgIcon(fixture).classList.contains('fa-spin')).toBeFalsy();
|
||||
expect(queryByCss(fixture, 'svg').classList.contains('fa-spin')).toBeFalsy();
|
||||
|
||||
fixture.componentInstance.isAnimated = true;
|
||||
fixture.detectChanges();
|
||||
expect(svgIcon(fixture).classList.contains('fa-spin')).toBeTruthy();
|
||||
expect(queryByCss(fixture, 'svg').classList.contains('fa-spin')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to create component dynamically', () => {
|
||||
@Component({
|
||||
selector: 'fa-host',
|
||||
template: '<ng-container #host></ng-container>'
|
||||
})
|
||||
class HostComponent {
|
||||
@ViewChild('host', {static: true, read: ViewContainerRef}) container: ViewContainerRef;
|
||||
|
||||
constructor(private cfr: ComponentFactoryResolver) {
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
const factory = this.cfr.resolveComponentFactory(FaIconComponent);
|
||||
const componentRef = this.container.createComponent(factory);
|
||||
componentRef.instance.icon = faUser;
|
||||
componentRef.instance.render();
|
||||
}
|
||||
}
|
||||
|
||||
const fixture = initTest(HostComponent);
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg')).toBeFalsy();
|
||||
|
||||
fixture.componentInstance.createIcon();
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to update icon programmatically', () => {
|
||||
@Component({
|
||||
selector: 'fa-host',
|
||||
template: '<fa-icon [icon]="faUser"></fa-icon>'
|
||||
})
|
||||
class HostComponent {
|
||||
faUser = faUser;
|
||||
|
||||
@ViewChild(FaIconComponent, {static: true}) iconComponent: FaIconComponent;
|
||||
}
|
||||
|
||||
const fixture = initTest(HostComponent);
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg').classList.contains('fa-spin')).toBeFalsy();
|
||||
|
||||
fixture.componentInstance.iconComponent.spin = true;
|
||||
fixture.componentInstance.iconComponent.render();
|
||||
fixture.detectChanges();
|
||||
expect(queryByCss(fixture, 'svg').classList.contains('fa-spin')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('custom service configuration', () => {
|
||||
|
@ -70,18 +104,18 @@ describe('FaIconComponent', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
library.add(faUser, faUserRegular);
|
||||
fixture = initTest(HostComponent);
|
||||
fixture = initTest(HostComponent, [{provide: FaIconService, useValue: {defaultPrefix: 'fas'}}]);
|
||||
});
|
||||
|
||||
it('should use default prefix', () => {
|
||||
fixture.detectChanges();
|
||||
expect(svgIcon(fixture).getAttribute('data-prefix')).toEqual('fas');
|
||||
expect(queryByCss(fixture, 'svg').getAttribute('data-prefix')).toEqual('fas');
|
||||
});
|
||||
|
||||
it('should override default prefix', inject([FaIconService], (service: FaIconService) => {
|
||||
service.defaultPrefix = 'far';
|
||||
fixture.detectChanges();
|
||||
expect(svgIcon(fixture).getAttribute('data-prefix')).toEqual('far');
|
||||
expect(queryByCss(fixture, 'svg').getAttribute('data-prefix')).toEqual('far');
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -82,6 +82,17 @@ export class FaIconComponent implements OnChanges {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Programmatically trigger rendering of the icon.
|
||||
*
|
||||
* This method is useful, when creating {@link FaIconComponent} dynamically or
|
||||
* changing its inputs programmatically as in these cases icon won't be
|
||||
* re-rendered automatically.
|
||||
*/
|
||||
render() {
|
||||
this.ngOnChanges({});
|
||||
}
|
||||
|
||||
protected normalizeIcon() {
|
||||
return faNormalizeIconSpec(this.icon, this.iconService.defaultPrefix);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Type } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
|
||||
import { IconDefinition, IconName, library } from '@fortawesome/fontawesome-svg-core';
|
||||
import { faUser } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FaDuotoneIconComponent } from '../lib/icon/duotone-icon.component';
|
||||
|
@ -10,7 +11,7 @@ import { FaLayersComponent } from '../lib/layers/layers.component';
|
|||
import { FaStackItemSizeDirective } from '../lib/stack/stack-item-size.directive';
|
||||
import { FaStackComponent } from '../lib/stack/stack.component';
|
||||
|
||||
export function initTest<T>(component: Type<T>): ComponentFixture<T> {
|
||||
export function initTest<T>(component: Type<T>, providers?: any[]): ComponentFixture<T> {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
FaIconComponent,
|
||||
|
@ -22,6 +23,15 @@ export function initTest<T>(component: Type<T>): ComponentFixture<T> {
|
|||
FaStackItemSizeDirective,
|
||||
component,
|
||||
],
|
||||
providers
|
||||
});
|
||||
TestBed.overrideModule(BrowserDynamicTestingModule, {
|
||||
set: {
|
||||
entryComponents: [
|
||||
FaIconComponent,
|
||||
FaDuotoneIconComponent,
|
||||
],
|
||||
},
|
||||
});
|
||||
library.add(faUser);
|
||||
return TestBed.createComponent(component);
|
||||
|
|
Loading…
Reference in New Issue