You can create a rendering component that will attach a view to it's own view, and then return the inner HTML.
The only issues is that the component must be rendered off page as the view has to be attached to the DOM, and you have to use a setTimeout() to allow the child component time to finish rendering.
Alternatively, you can use a ngTemplate reference instead of a component factory. The two are basically the same when you are attaching to a ViewContainerRef.
Here is an example that I wrote, but I haven't tried it:
@Component({
selector: 'app-render',
template: '',
styles: [
'position: absolute',
'top: -99999',
'left: -99999'
],
exportAs: 'appRender'
})
export class RenderComponent {
constructor(private view: ViewContainerRef,
private el: ElementRef<HTMLElement>) { }
public function compile(factory: ComponentFactory<any>): Promise<string> {
return new Promise(resolver => {
this.view.createComponent(template);
setTimeout(() => {
resolver(this.el.nativeElement.innerHTML);
this.view.clear();
});
});
}
}
You have to add the <app-render> component somewhere in your app, and then call compile(myComponent) which returns a promise with the HTML as a string.
If your child component uses *ngIf or *ngFor then the duration of setTimeout() needs to be increased, or you call multiple setTimeout() functions. Either way, you need time for the HTML to be rendered by Angular.
It's not possible with a different approach to create synchronized function that yields HTML from a component as a string. Angular doesn't work that way.