<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>angular 5 + flex layout</title>
     <!-- polyfill(s) for older browsers -->
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>

    <script src="https://unpkg.com/zone.js@0.8.16?main=browser"></script>
    <!--<script src="https://unpkg.com/reflect-metadata@0.1.10"></script>-->
    <script src="https://unpkg.com/systemjs@0.20.18/dist/system.src.js"></script>
    <script src="https://unpkg.com/web-animations-js@2.3.1"></script>
  

    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) { console.error(err); });
    </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
### Angular Starter Plunker - Typescript
//our root app component
import { Component, NgModule, VERSION} from '@angular/core';
import { BrowserModule} from '@angular/platform-browser';

@Component({
  selector: 'my-app',
  template: `<h1>Angular - Dynamic content click event</h1>
            <p>Angular 2, Angular 5, Typescript - User click events/event handling for dynamic [innerHTML] generated content using pipe and directive to generate and converting plain text to click urls e.g #hashtags,  @Handle, @Mention, #routerLink #href and #mailto etc</p>
            <ul>
              <li *ngFor="let item of theList; let $index=index;" [innerHTML]="item | parseUrl" [dynamicContent]="currentView"></li>
            <ul>`
})
export class AppComponent {
   theList:Array;
    
    constructor() {
        this.theList = [
          'Lorem ipsum dolor sit amet, consectetur @adet dolore magna aliqua. Ut enim ad minim veniam',
          'Lorem ipsum dolor sit amet, consectetur adipiscing http://google.com sed do eiusmod tempor #incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
          'Lorem http://google.com ipsum dolor #sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt gna aliqua. Ut enim ad minim veniam',
          'Lorem ipsum @dolor sit amet, consectetur @adipiscing elit, sed do eiusmod @tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
          'Lorem ipsum dolor sit amet, smod tempor incididunt #ut labore et dolore @magna #aliqua. Ut enim ad minim veniam',
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
          'Lorem ipsum @dolor sit amet, #consectetur adipiscing elit, sed do eiusmod tempor http://google.com enim ad minim veniam'
        ];
    }

}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { FlexLayoutModule } from '@angular/flex-layout';

import { ParseUrl } from './parse-url.pipe';
import { DynamicContent }  from './dynamic-content.directive';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        FlexLayoutModule
    ],
    declarations: [
        AppComponent,
        ParseUrl,
        DynamicContent
    ],
    exports: [

    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
(function (global) {
  var angVer = '5.0.0-beta.6';
 
  System.config({
    transpiler: 'ts',
    typescriptOptions: {
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "lib": [ "es2015", "dom" ],
      "module": "commonjs",
      "moduleResolution": "node",
      "noImplicitAny": true,
      "sourceMap": true,
      "suppressImplicitAnyIndexErrors": true,
      "target": "es5"
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: { 
      'npm:': 'https://unpkg.com/',
      'gh:': 'https://raw.githubusercontent.com/'
    },
    map: {
      "app": "app",
      "rxjs": "npm:rxjs@5.4.3",
      "ts": "npm:plugin-typescript@7.1.0/lib/plugin.js",
      "typescript": "npm:typescript@2.4.2/lib/typescript.js",
      "@angular/core": "npm:@angular/core@" + angVer + "/bundles/core.umd.js",
      "@angular/common": "npm:@angular/common@" + angVer + "/bundles/common.umd.js",
      "@angular/compiler": "npm:@angular/compiler@" + angVer + "/bundles/compiler.umd.js",
      "@angular/platform-browser": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser.umd.js",
      "@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@" + angVer + "/bundles/platform-browser-dynamic.umd.js",
      "@angular/http": "npm:@angular/http@" + angVer + "/bundles/http.umd.js",
      "@angular/router": "npm:@angular/router@" + angVer + "/bundles/router.umd.js",
      "@angular/forms": "npm:@angular/forms@" + angVer + "/bundles/forms.umd.js",
      "@angular/animations": "npm:@angular/animations@" + angVer + "/bundles/animations.umd.js",
      "@angular/animations/browser": "npm:@angular/animations@" + angVer + "/bundles/animations-browser.umd.js",
      "@angular/platform-browser/animations": "npm:@angular/platform-browser@" + angVer + "/bundles/platform-browser-animations.umd.js",
      "@angular/flex-layout": "npm:@angular/flex-layout@2.0.0-beta.9"
},
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.ts',
        defaultExtension: 'ts'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });

  if (!global.noBootstrap) { bootstrap(); }

  // Bootstrap the `AppModule`(skip the `app/main.ts` that normally does this)
  function bootstrap() {

    // Stub out `app/main.ts` so System.import('app') doesn't fail if called in the index.html
    System.set(System.normalizeSync('app/main.ts'), System.newModule({ }));

    // bootstrap and launch the app (equivalent to standard main.ts)
    Promise.all([
      System.import('@angular/platform-browser-dynamic'),
      System.import('app/app.module')
    ])
    .then(function (imports) {
      var platform = imports[0];
      var app      = imports[1];
      platform.platformBrowserDynamic().bootstrapModule(app.AppModule);
    })
    .catch(function(err){ console.error(err); });
  }
})(this);
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ 
    name: 'parseUrl',
    pure: false
})

export class ParseUrl implements PipeTransform {

	urls: any = /(\b(https?|http|ftp|ftps|Https|rtsp|Rtsp):\/\/[A-Z0-9+&@#\/%?=~_|!:,.;-]*[-A-Z0-9+&@#\/%=~_|])/gim; // Find/Replace URL's in text	
	hashtags: any = /(^|\s)(#[a-z\d][\w-]*)/ig; // Find/Replace #hashtags in text	
	mentions: any = /(^|\s)(@[a-z\d][\w-]*)/ig; // Find/Replace @Handle/Mentions in text	
	emails: any = /(\S+@\S+\.\S+)/gim; // Find/Replace email addresses in text
     
  transform(text: string) {
    return this.parseUrl(text);
  }

  private parseUrl(text: string) {
    // Find/Replace URL's in text
    if (text.match(this.urls)) {
        text = text.replace(this.urls, function replacer($1, $2, $3) {
            let url: any = $1;
            let urlClean: any = url.replace("" + $3 + "://", "");

            return "<a href=\"" + url + "\" target=\"_blank\">" + urlClean + "</a>";
        });
    }
    
    // Find/Replace @Handle/Mentions in text
    if (text.match(this.hashtags)) {
      text = text.replace(this.hashtags, "<a href=\"/search/hashtag/$2\" class=\"hashtag-link\">$1$2</a>");
    }

    // Find/Replace #hashtags in text
    if (text.match(this.mentions)) {
      text = text.replace(this.mentions, "<a href=\"/search/handle/$2\" class=\"handle-link\">$1$2</a>");
    }

    // Find/Replace email addresses in text
    if (text.match(this.emails)) {
        text = text.replace(this.emails, "<a href=\"mailto:$1\">$1</a>");
    }

    return text;
  }  
}
/* tslint:disable:member-ordering */
import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[dynamicContent]'
})
export class DynamicContent {

  constructor(private el: ElementRef) { }

  @Input('dynamicContent') dynamicContent: string;

  @HostListener('click', ['$event']) onClick(e) {
    
    if (e.target.classList.contains('handle-link')) {
      let link: string = e.target.innerHTML;

      event.preventDefault();
      event.stopPropagation();
     
      alert("/search/handle/" + link.trim());
      
      //this.router.navigateByUrl("/search/handle/" + link.trim(), { skipLocationChange: false });
      
    } else if (e.target.classList.contains('hashtag-link')) {
      let link: string = e.target.innerHTML;

      event.preventDefault();
      event.stopPropagation();
      
       alert("/search/hashtag/" + link.trim());
       
      //this.router.navigateByUrl("/search/hashtag/" + link.trim(), { skipLocationChange: false }); 
      
    }
    
  }

}