I do something similar to display an html file constructed by an external application.
I use a wrapper component, passing in the html as an input parameter and implementing the ngOnChanges lifecycle hook to let Angular know there's a change to the html.
import { Component, Input, ElementRef, OnChanges } from '@angular/core';
@Component({
selector: 'result-wrapper',
template: `<div data-container></div>`
})
export class ResultWrapper implements OnChanges {
@Input() displayString: string;
constructor(
private elementRef: ElementRef,
) {}
ngOnChanges() {
this.setPageContent();
}
setPageContent() {
const outerDiv = this.elementRef.nativeElement.querySelector('div[data-container]');
outerDiv.innerHTML = this.displayString;
}
}
Changes to the raw html are made in the parent component of ResultWrapper and passed in via attributes.
I use standard document methods as these seem most convenient. For example:
const tempDiv = document.createElement('div');
tempDiv.innerHTML = displayString;
const dataCardText = tempDiv.querySelector('text[data-card-text]');
dataCardText.value = this.myValue;
return tempDiv.innerHTML;
A further note, if you want to style the displayString you should probably add style tags directly to it as Angular will have applied styles defined in @Component before your inner html is updated. Note that styles can 'bleed' into other parts of the page, so make sure they reference the data-container
attribute in the wrapper template.
I'm assuming that the tags <svg>
and <text data-card-text>
may differ at runtime, if not you are obviously better off putting them in the template and interpolating the value. This would not need a wrapper component as {{myValue}}
changes would be detected automatically.
@Component({
selector: 'my-selector',
template: `<svg><text data-card-text>{{myValue}}</text></svg>`
})