1

I have a backend database containing help manual topics in html format, including anchors with on click function. My Angular (4.3.5) app has a tree of topics, when a tree topic is clicked the topic's body html is got from the backend and displayed next to the topic tree in a container div.

My question is about how to display the html page in the container div. Initially I tried:

<div [innerHtml]="htmlbody | safeHtmlPipe"></div>

This solution did not fully work because the htmlbody contains anchors to other pages as:

<a (click)="loadNewPage(topicId)">display topic</a>

Angular is sanitizing (filtering out) the anchor on click handler.

I have followed many google links on this subject like Dynamically displaying elements containing HTML with (click) functions Angular 2. Also I have looked at a wrapper component as in Dynamic Injection in Angular 4. But failed to find any actual examples of working code that specifically provides loading html from a dynamic source (ex the backend). I would like to make use of the new ngComponentOutlet directive and have it AoT compatible.

Does anyone know how to achieve this?

0

1 Answer 1

1

Since no one answered this question, here is a working solution albeit it not the ideal it does work perfectly. And is AOT compliant.

Template:

<div id="pagecontainer" [innerHtml]="htmlbody | safeHtmlPipe"></div>

The following code replaces all dom anchor hrefs inside the pagecontainer with a click callback:

// use service to get backend html
this.db.get('getpage', pageId)
.subscribe(res => {
    // load innerHtml with page markup
    this.htmlPage = res.data;
    // short pause (for template [innerHtml] = htmlbody)
    setTimeout(() => {
        // get all achors children of the page container
        let pc = document.body.querySelector("#pagecontainer");
        let x = pc.querySelectorAll('a');
        Array.from(x).forEach(el => {
            // get the href content
            let hr = el.getAttribute('href');
            if (hr != undefined) {
                // replace href with onclick event
                el.setAttribute('href', 'onclick=\"link()\"');
                // bind click listener
                el.addEventListener('click', e => {
                    // prevent browser precessing the anchor
                    e.preventDefault();
                    // callback with original href content
                    this.link(hr);                  
                });
            }
        });
        // scroll to the first h1
        pc.getElementsByTagName('h1')[0].scrollIntoView();
        this.g.showloading = false;
    }, 100);
});

link(href) {
  // call the topic on click handler with href to load the new page
}

And for the sake of completeness, the safeHtml pipe:

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

// Ref: https://stackoverflow.com/questions/39794588/angular2-innerhtml-removes-styling

@Pipe({
  name: 'safeHtmlPipe'
})

export class safeHtmlPipe implements PipeTransform {

  constructor(private sanitizer:DomSanitizer){}

  transform(html) {         
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }
}
Sign up to request clarification or add additional context in comments.

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.