1

I'm not exactly sure what to call this so I might have missed some things in my search for an answer for this but basically I have data that comes in from an external api and it gets inserted into an innerHTML tag now in the data that is being returned is some html which then gets processed thanks to innerHTML but I have certain keywords in the returned html like this [username] and I want to replace that with data I have stored. So in my .ts file I might have..

username: 'name';

then in my html I have

<div class='inner-html' [innerHTML]="data.html"></div>

and in my response from data.html the html is like so

<h1>Hey [userName] lorem ipsum...</h1>

so I want to replace the [userName] that comes in dynamically from the external api with the username that is stored in username

I tried to put {{username}} in the html that is coming in.. but that didnt work and I also tried ${username} but that also didnt work..

Im wondering if there is another way?

EDIT Ive tried to use str.replace(); in the onChanges life cycle event but that isn't working either my code is ..

  const html = <HTMLElement>document.querySelector('.inner-html');
  html.innerHTML.replace('[userName]', this.username);

Now something like this must be possible, any help would be appreciated

Thanks

Smokey Dawson
  • 8,827
  • 19
  • 77
  • 152

3 Answers3

2

Angular provides the Pipe precisely for this purpose:

Pipe

An Angular pipe is a function that transforms input values to output values for display in a view.

They provide reusable and scalable ways of accomplishing your goal. Please check this out as I think it is what you are after:

Live Solution

Basically, you pipe the output of the [innerHTML] through a transform:

<div class='inner-html' [innerHTML]="data.html | parseInnerHtml:replacements"></div>

parseInnerHtml is the custom pipe and it takes a hash of replacement keys and corresponding values to replace with:

import { Input, Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'parseInnerHtml'})
export class ParseInnerHtml implements PipeTransform {
  transform(text: string, replacements: Object): string {
    let search = Object.keys(replacements);
    for(let i = 0; i < search.length; i++){
      text = text.replace('['+ search[i] +']', replacements[search[i]]);
    }
    return text;
  }
}
Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
  • 1
    You should modify you replacement method so that it works if the string to replace is there more than one time – David Mar 23 '18 at 09:19
  • Good suggestion, but I'll allow the OP to do that if so desired. I've answered the question as asked. – Randy Casburn Mar 23 '18 at 14:24
  • @Randy Casburn Hey there just one quick question.. this works perfectly but.. Im getting an error in the console that says `cannot convert undefined or null to object on line 5 of the parseInnerHtml pipe` Im assuming this is because the data hasnt come in yet before this call is made.. is there anyway to avoid this?? – Smokey Dawson Mar 25 '18 at 22:24
  • That sounds like you didn't create an object that has the replacements. this is shown in the solution in app.component.ts @ line 9. Did you create? – Randy Casburn Mar 26 '18 at 01:09
0

It looks like you have control of the dynamic data. If that is so, It would make more sense if you could transform the html on the server to include the username.

However if you don't have control, you could easily use replace the [username] with what you have. E.G:

str.replace('[username]', this.username);

oreofeolurin
  • 636
  • 3
  • 16
0
-- in hello.component.ts
@Component({
  selector: 'hello',
  template: ``,
})
export class HelloComponent  {
  @Input() username: string;

  private _html: string;
  @HostBinding('innerHTML')
  @Input() set html(html: string) {
    this._html = html.replace('[userName]', this.username);
  }

  get html() {
     return this._html;
  }
}

-- in app.component.html
<hello [html]="html" [username]="username"></hello>

-- in app.component.ts
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  username = 'App user';
  html = '<h1>Hello [userName]!</h1>';
}

Live example

Tomasz Kula
  • 16,199
  • 2
  • 68
  • 79