4

In my Angular 2 app, I am displaying messages using an ngFor loop. These messages contain URLs. I am using a custom pipe to parse the messages and make the URLs clickable. Additionally, if the URL is a link to a YouTube video, I turn the link into embed code.

Because of performance reasons, I would like to initially display thumbnails of the videos, and switch to the embed code only when the user clicks the thumbnail. To achieve that and not make a tangled hairy mess, I would like to give each video its own custom component. I just have to pass in the video ID and then everything can be handled in the component.

I can get my pipe to return HTML, but if I make it return a custom component (for example: <youtube-video [videoID]="xxx"></youtube-video>), the component never gets processed by Angular, and so it doesn't work.

Is this at all possible, and how would I go about it?

This is my pipe:

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

let linkify     = require('linkifyjs');
let linkifyHtml = require('linkifyjs/html');
let linkifyStr  = require('linkifyjs/string');

@Pipe({
    name: 'linkify'
})
export class LinkifyPipe implements PipeTransform {
    constructor(private domSanitizer: DomSanitizer) {}

    transform(value: string) {
        if (!value) return value;

        let ytRegExp: RegExp = /^.*(youtu.be\/|v\/|e\/|u\/\w+\/|embed\/|v=)([^#\&\?]*).*/; // parse YT link
        let urls: any[] = linkify.find(value); // get all URLs
        urls.forEach((url) => {
            if (ytRegExp.test(url.value)) { // it's a YT video
                let videoID = url.value.replace(ytRegExp, '$2');
                value = value.replace(url.value, '<iframe width="320" height="180" src="https://www.youtube.com/embed/' + videoID + '?rel=0" frameborder="0" allowfullscreen></iframe>');
            }
        });

        return this.domSanitizer.bypassSecurityTrustHtml(linkifyHtml(value));
    }
}
Brother Woodrow
  • 6,092
  • 3
  • 18
  • 20

1 Answers1

2

Angular2 doesn't process HTML added to the DOM dynamically like element.appendChild() or [innerHTML] except some sanitization for security.

[xxx]="yyy", (event)="handler" or{{content}}` are not processed and also components and directives where selectors would match and not instantiated.

Angular instantiates components and directives only for HTML statically added to a components template.

One exception is ViewContainerRef.createComponent().
See Angular 2 dynamic tabs with user-click chosen components for an example.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567