11

I need to provide a solid HTML string to my maps marker baloon body.
I want to make the baloon an Angular component and use bindings and built-in directives (*ngFor, *ngIf, etc). So Im looking for a way to evaluate all bindings in component template and compile result to a string...
How to achieve this or if this approach is non-angular - what could be the pattern recommended?

// Component

import {Component} from '@angular2/core';
import {AnyThing} from './somewhere/in/my/app/anything.model.ts';

@Component({
  selector: 'my-baloon-window',
  template: `<p>This is a baloon for {{ any.name }}</p>`
})
export class MyBaloonWindowComponent {
    constructor(public something: AnyThing) {}
}


// Implementation

import {AnyThing} from './somewhere/in/my/app/anything.model.ts';
import {MyBaloonWindowComponent} from './path/to/baloon-window.component';

/* { ...some code here... } */

private createBaloonWindow(thing: AnyThing): google.maps.InfoWindow {
    return new ymap.map.BaloonWindow({
      /* I want something like this */
      content: new MyBaloonWindowComponent(thing).toString() 
      /* ^ this is what I want ^ */
    });
}
3
  • I looked into this recently, and I don't think there's anything that currently exposes this. We ended up just writing our own function using multiline templates strings, instead of the Angular template syntax. Commented Oct 10, 2017 at 11:00
  • Im investigating this for a while and there are some hints that it is maybe possible by using some technics like elementRef, or/and ReflectiveInjector, Rendered etc... Still hoping to find the one solid and beautiful solution for this :) Commented Oct 10, 2017 at 11:40
  • 4
    from '@angular2/core'; You seem to be kidding Commented Oct 13, 2017 at 13:54

3 Answers 3

2

I'm sort of surprised no one has suggested using Angular Universal -- yes, at least as of the 2.0 compatible version it rendered an entire document, but you could load your singular component into a page, render to an html string with angular universal, and then strip out the <html> tags etc.

https://github.com/angular/universal

Angular Universal is designed to render HTML on the server side, which is fundamentally about exposing the rendering engine to code without relying on the DOM.

Also of note, if you want to access the Renderer or RootRenderer directly in Angular 4, you'll have to generate a new instance using the RendererFactory -- but both of these were exposed directly in Angular 2

https://jaxenter.com/angular-4-top-features-133165.html

Sign up to request clarification or add additional context in comments.

Comments

1

You could try to render MyBaloonWindowComponent into hidden div and then using delay i.e. setTimeout(..., 0) or more advanced scheduling, helper service or custom event receive resulting html from injected ElementRef.

It is possible to create special component(like NgComponentOutlet) + service that will do rendering and then emit resulting html to client code.

Comments

1

Just posting here because I don't find the accepted answer as the solution to the question. Angular Universal should be considered as a whole application rendering setup change. For a small HTML-parsing feature, changing the whole app into Angular universal doesn't make sense. Also, the conversion could lead to compatibility issues in complex projects if you are not good with the concepts of SSR and CSR.

I recently got into the same situation where I need to parse the angular component's HTML as a string with all the bindings and stuff.

It seems Angular does not expose a method to get this done. Here is what I did to parse the component HTML as a string.

app.component.html (check stackblitz link for all files)

import {
  Component,
  ComponentFactory,
  ComponentFactoryResolver,
  ViewChild,
  ViewContainerRef,
} from '@angular/core';
import { asyncScheduler } from 'rxjs';
import { PdfHtmlComponent } from './pdf-html.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  @ViewChild('pdfHtml', { read: ViewContainerRef }) container;

  constructor(private resolver: ComponentFactoryResolver) {}

  getPDFHtml() {
    this.container.clear();
    const factory: ComponentFactory<any> =
      this.resolver.resolveComponentFactory(PdfHtmlComponent);

    const componentRef = this.container.createComponent(factory);
    componentRef.instance.title = 'Injected Title';

    asyncScheduler.schedule(() => {
      const htmlString = componentRef.location.nativeElement.innerHTML;
      componentRef.destroy();
      console.log('HTML STRING:', htmlString);
    });
  }
}

You can see the demo here https://parse-angular-component-html-as-string.stackblitz.io

or you can play with the code here https://stackblitz.com/edit/parse-angular-component-html-as-string?file=src/app/app.component.ts

Happy coding!!! 🎉🎉🎉

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.