Reputation: 83
I investigated the problem for dynamic load of fontawesome icon by iconName. But the code is not working. What is the reason? What is the best practice? And why I need the call for ngOnChanges() in the directive ngOnInit() hook? The error I get in the browser is "FontAwesome: Could not find icon. It looks like you've provided a null or undefined icon object to this component."
import { AppComponent } from './app.component';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library, dom } from '@fortawesome/fontawesome-svg-core';
import { fas,faCheck, faCalendar, faTimes } from '@fortawesome/free-solid-svg-icons';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { IconDirective } from './icon.directive';
@NgModule({
declarations: [AppComponent, IconDirective],
imports: [BrowserModule, FontAwesomeModule],
providers: [],
bootstrap: [AppComponent],
entryComponents: [FaIconComponent],
})
export class AppModule {
constructor() {
library.add(fas,faCheck, faCalendar, faTimes);
dom.watch();
}
}
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<div iconDirective></div>'
})
export class AppComponent {
constructor() { }
}
import { Directive, OnInit, ViewContainerRef, ComponentFactoryResolver }
from '@angular/core';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faCheck, faCalendar, faTimes } from '@fortawesome/free-solid-svg-icons';
import { icon } from '@fortawesome/fontawesome-svg-core';
@Directive({
selector: '[iconDirective]'
})
export class IconDirective{
constructor(
public viewContainerRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver) {
}
ngOnInit() {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(FaIconComponent);
const componentRef =
this.viewContainerRef.createComponent(componentFactory);
(<FaIconComponent>componentRef.instance).icon =
icon({iconName: 'times', prefix: 'fas'});
// (<FaIconComponent>componentRef.instance).iconProp = faCheck; //works
(<FaIconComponent>componentRef.instance).ngOnChanges({});
}
}
Upvotes: 3
Views: 4149
Reputation: 14535
Since the 0.5.0 release angular-fontawesome
has a better support for rendering icon component dynamically. Check out the official documentation:
@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();
}
}
What is the reason? The error I get in the browser is "FontAwesome: Could not find icon. It looks like you've provided a null or undefined icon object to this component."
Because you should have set iconProp
input property, not icon
property, which was errornously exposed on the component. Note that this is no longer the case in >0.5.0 (see example above).
What is the best practice?
See example above.
And why I need the call for ngOnChanges() in the directive ngOnInit() hook?
Because icon rendering is triggered by a call to ngOnChanges
hook, which is performed by the Angular framework when you add component in the template. When creating a component dynamically Angular does not call this hook, so you need to do it manually. Note that in >0.5.0 there is a dedicated method, which triggers rendering without relying on this implementation detail - FaIconComponent.render()
.
Upvotes: 2