Dynamically add color in ion-card text based on regex

I want to add a span around some text when a # or a @ is detected so I can change the color to make it look like usernames and hashtags in twitter. My code looks like this:

TS FILE:

ngOnInit(): void {
    this.glyphService.getAllGlyphs().subscribe(
      result => {
        this.items = result;
        // sort by rune id so list is newest to oldest
        this.items.sort((a, b) => Number(b.rune) - Number(a.rune));
        for (let i = 0; i < this.items.length; i++) {
          this.items[i].glyph_content = this.replaceIt(this.items[i].glyph_content);
          console.log(this.items[i])
        }
        console.log(this.items)
      }
    );
  }

  replaceIt = (str: string) => {
    const regex = /\B([\#\@][a-zA-Z]+\b)(?!;)/g;
    const subst = `<span style="color:blue">$1</span>`;
    const result = str.replace(regex, subst);
    return result;
 }

HTML FILE:

  <ion-card *ngFor="let item of items" >
    <ion-card-header>
      <ion-card-title>&#64;{{item.username}}</ion-card-title>
      <ion-card-subtitle>{{item.glyph_date}}</ion-card-subtitle>
    </ion-card-header>
    <ion-card-content>
      {{item.glyph_content}}
    </ion-card-content>
 </ion-card>

I’m successfully replacing the text like I want to, however it’s just winding up as text instead actual tags and looks like this:


Is there a way for me to change my code so I’m actually dynamically wrapping the target text in real spans like I want?

By default, Angular is going to escape HTML characters. You need to set it using innerHTML. You need to be careful with this though if it is user generated text. You would want to sanitize the text first before running your formatting logic. This is probably a good reference - Angular innerHTML and DomSanitizer: Complete Guide.

<ion-card-content [innerHTML]=item.glyph_content</ion-card-content>

In my testing, it looks like IonCardContent doesn’t keep the style attribute. It does keep class. Since the content is in the Shadow DOM, you will need to set the class styles in your global.css to have affect.

Another option is to only use IonCard and not the other Ionic inner components in order to have full control. This is what I do.

That worked! If i use innerHTML and import DomSanitizer in the TS file and then do this:

          this.items[i].glyph_content_html = this.sanitizer.bypassSecurityTrustHtml(
            this.replaceIt(this.items[i].glyph_content)
          );

Then the text appears blue as I want it to. Thanks mate! I understand I’ll need to make sure it’s sanitized if I allow users to input text, for now this app is just a POC so that’s not necessary but I know that’ll be needed in a real version.

1 Like