3

Here's my scenario. Users enter content via tinyMCE editor, and I display this content to the user in a component like so:

@Component({
    template: '
        <h3>Description</h3>
        <div [innerHTML]="content"></div>
    '
})
export class DetailsComponent implements OnInit {

    content: string = "";

    constructor(private service: any){}

    ngOnInit(){
        this.service.loadDetails().pipe(
            tap((result) => this.content = result)
        ).subscribe();
    }
}

Now the content from the server can be anything. So if the server returns this content:

<p>This is my content from the server. <img src="..." /></p>

Then my DetailsComponent output would look like this:

<h3>Description</h3>
<div>
    <p>This is my content from the server. <img src="..." /></p>
</div>

I want to write a component to replace any images with a custom component. How do you do this without using an existing #template reference?

Essential, it could look like this where my custom component wraps the image:

<h3>Description</h3>
<div>
    <p>This is my content from the server. <custom-component><img src="..." /></custom-component></p>
</div>
2
  • 1
    So basically what you need to do is create a dynamic component with the template you are fectching from the server. Is that right? Commented Aug 29, 2018 at 4:21
  • @AnuradhaGunasekara Yup, this is what I'm needing Commented Aug 29, 2018 at 13:59

1 Answer 1

0

Found a solution by working off this SO example

Here's how I solved the problem.

update() {

    let images = this.el.nativeElement.querySelectorAll('img');

    for (let x = 0; x < images.length; x++) {
        const img = images[x];

        let clone = img.cloneNode(true);
        // Important because angular removes all children of a node. 
        // So wrap the image, and then use the wrapper as the root node for the component to attach to
        $(img).wrap("<span />");
        let factory = this.factoryResolver.resolveComponentFactory(CustomComponent);
        let ref = factory.create(this.injector, [[clone]], img.parentNode); //use a clone as the projectable node, and use its parent (the wrapper span) as the rootNode

        this.applicationRef.attachView(ref.hostView);
        ref.changeDetectorRef.detectChanges();
        this.components.push(ref); //save the references later so that I can destroy them
    }
}
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.