如何在Angular 5中将指令应用于innerHtml中的元素?

时间:2018-08-15 15:46:10

标签: angular ionic3 innerhtml angular2-directives

这是针对Angular 5 / Ionic 3应用程序的。 我有一个div,其中从富文本编辑器显示用户生成的html:

<div [innerHtml]='text'></div>

此数据可以包括<a href>个链接,我需要为其捕获click事件以强制在系统的默认浏览器中打开。

我制定了一条指令,该指令可以完美地处理静态内容,但不会影响innerHtml元素内的任何内容。

import { Directive, Input, HostListener } from "@angular/core";
import { InAppBrowser } from "@ionic-native/in-app-browser";

@Directive({
  selector : '[href]'
})
export class PreventLink {

  @Input() href;

  constructor( private iab: InAppBrowser ) {};

  @HostListener('click', ['$event'])
  public onClick( event: Event ) {

    if( event && this.href ) {

      if( this.href.length > 0 ){
        this.iab.create( this.href, '_system' );
      }

      event.preventDefault();
      return false;
    }
  };
};

任何实现我需要的想法都会受到赞赏。

2 个答案:

答案 0 :(得分:1)

如果有人想知道如何做,我将在这里发布我的hacky解决方案。我仍然希望有一个更好,更“角度”的解决方案来实现这一目标。

首先,我们需要在 index.html 中准备一个基本的javascript代码段,以了解何时单击锚点。将其放在本节的末尾。

<script>
  document.onclick = function (e){
    e = e || window.event || {};
    var element = e.target || e.srcElement;

    if (element && element.tagName == 'A') {

      handleAClick( element.href );

      e.preventDefault();
      return false;
    }
  };

  function handleAClick(){}; //Just a placeholder until the angular app is ready
</script>

然后在 app.component.ts 中,我将使用实际交易覆盖 handleAClick 函数:

import { Component, OnInit, ViewChild } from '@angular/core';
import { InAppBrowser } from '@ionic-native/in-app-browser';
import { Platform } from 'ionic-angular';


@Component({
  templateUrl: 'app.html'
})

export class MySuperApp implements OnInit {

  constructor( private platform: Platform, private iab: InAppBrowser ){};

  ngOnInit() {

    this.platform.ready().then( () => {

      let win = (<any>window);
      win.handleAClick = ( url: string ) => {
        this.handleAClick( url );
      };
    });
  };


  private handleAClick( href: string ) {

    if( href && href.length > 0 ) {
      this.iab.create( href, '_system' );
    }
  };
};

答案 1 :(得分:1)

这篇文章已经很老了,但是如果有人遇到这个问题,我使用了几乎相同的自定义指令解决了这个问题,那么可以确定该设置可以使用angular 9 / ionic 5对我起作用。

import { Directive, HostListener } from '@angular/core';

/**
 * Custom directive so that we can listen for clicks (or taps) on the event detail page.
 * When the user clicks on an embeded link it will be opened by the browser service and now what ever target
 * the link was written for.
 * Since we dont control the content of the event feed descriptions this is the only way we can control
 * what happens when they include a link and the user opens it.
 */
@Directive({
    selector: '[linkInterceptor]',
})
export class LinkIntereptorDirective {

    @HostListener('click', ['$event']) onClick(event: any) {
        this.clickJack(event);
    }

    @HostListener('tap', ['$event']) onTap(event: any) {
        this.clickJack(event);
    }

    private clickJack(event) {
        event.preventDefault();
        if (event.target.tagName.toLowerCase() === 'a') {
            this.open(event.target.href);
        }
    }

    private async open(href) {
        // here you can handle how you want to open the url.
    }

    constructor() { }
}

模板:

<div *ngIf="content.length" class="ion-padding-horizontal" tappable linkInterceptor [innerHtml]="getHtml()"></div>

组件:

  /**
   * For somereason on ionic when you use the pipe syntax to sanitize
   * html it makes the content block not clickable. So this fixes that so we can register our custom link interceptor directive.
   */
  getHtml(): SafeHtml {
    return this.domSanitizer.sanitize(SecurityContext.HTML, htmlContent);
  }