Visibly0467
Visibly0467

Reputation: 65

How to show a dynamically inserted fontawesome icon in template through innerHTML?

I am looking for a way to display text (markdown) on page that can contain a fontawesome icon. The framework is Angular 15 and fortawesome 6 has been used.

The text is dynamically inserted through an innerHTML tag. Through a markdown pipe I was able to convert the text (in markdown) to semantically correct HTML. Unfortunately, regarding the parse of the icons, I have not found a good solution for the moment. What I don't understand is, how do I prevent ng/security#xss from cleaning up my code and simultaneously have the icon placeholder convert to call the fontawesome component and display it?

I tried using

content.replace(/{!!icon!!}/g, '<fa-icon [icon]="faCoffee"></fa-icon>')

to replace the placeholder {!!icon!!} with the icon. However, Angular's security intervenes and kills the <fa-icon [icon]="faCoffee"></fa-icon>. So I attempted to use return this.domSanitizer.bypassSecurityTrustHtml in pipe to prevent the ng/security#xss from killing my code. This works but the icon is not displayed because the code <fa-icon [icon]="faCoffee"></fa-icon> is not interpreted.

@Pipe({
  name: 'sanitizer'
})
export class SanitizerPipe implements PipeTransform {

  constructor(private domSanitizer: DomSanitizer) { }

  transform(content: string, ...args: unknown[]): unknown {
      return this.domSanitizer.bypassSecurityTrustHtml(this.iconParser(content)) as SafeHtml;
    }
  }

  private iconParser = (content: string) => {
    return content.replace(/{!!icon!!}/g, `<fa-icon [icon]="faCoffee"></fa-icon>`);
  }

}

I saw a question asked quite some time ago they had solved by injecting the fontawesome component. So my approach is easily wrong, however I have no idea how I could solve it with this.

Angular's unnecessarily complicated "documentation"(API), says nothing on this topic, as usual.

Upvotes: 4

Views: 417

Answers (2)

Visibly0467
Visibly0467

Reputation: 65

This particular problem is solved directly by Fontawesome through this guide. The library (angular-fontawesome) provides the function icon(). This solves the problem as you just need to do:

import { icon } from '@fortawesome/fontawesome-svg-core';

...

private iconParser = (content: string) => {
  return content.replace(/{!!icon!!}/g, `${icon(faCoffee).html.join('')}`);
}

The icon(faCoffee).html.join('') code generates a valid SVG:

<svg aria-hidden="true" focusable="false" ... ><path fill="currentColor" ...></path></svg>

Upvotes: 1

Naren Murali
Naren Murali

Reputation: 56097

Content rendered inside innerHTML exists outside the angular context, so fa-icon component does not exist! that is why you are getting this issue. Generally, content inside innerHTML should not contain any angular functionality. Since you just want to render a font, you can use the original font awesome html to do this.

<i class="fa fa-coffee" aria-hidden="true"></i>

in the pipe it will be

private iconParser = (content: string) => {
    return content.replace(/{!!icon!!}/g, `<i class="fa fa-coffee" aria-hidden="true"></i>`);
  }

Upvotes: 2

Related Questions