Databinding/interaction 包含用户创建的内容

Databinding/interaction with user created content

我的最终目标是让用户创建 HTML(从数据库)能够在 Angular SPA 中导航。从后端显示 HTML 的简单方法是使用 DomSanitizer 然后绑定到某个元素的 innerHTML。当用户创建的内容中的锚标记 <a href="/path/to/diffrent/page/in/app"> 重新启动应用程序时,就会出现问题。我想过3个方案,都存在问题

注意:我想充分利用 AOT 和构建优化器。

  1. (带有 JIT 编译器的动态组件)
    用户创建的内容将具有 angular 语法,如 <a [routerLink]="/path/to/diffrent/page/in/app">。然后使用示例 here of loading the runtime compiler with JitCompilerFactory and custom decorators to preserve the component and module metadata to JIT compile components with the user created content as templates. However with build-optimizer this requires . With this you don't get all the size benefits of AOT because you still need to load the JIT compiler and as stated - 》 这似乎是有风险的,因为编译器会受到内部变化的影响。它适用于@angular/compiler@4.4.5,但可能不适用于其他版本。"

  2. (DOM 操纵)
    在用户创建的内容 <a href="/path/to/diffrent/page/in/app"> 中保留适当的 HTML。然后在绑定到 innerHTML 之后得到一个 ElementRef,然后找到每个锚标记并覆盖点击事件。这种 DOM 操作在 angular.

  3. 中似乎非常令人沮丧
  4. (自定义 window 事件)
    用户创建的内容将类似于 <a onclick="window.someGlobalFunc("/path/to/diffrent/page/in/app")">。然后以某种方式在 angular 中收听 window 事件。我更不喜欢这个想法,因为它完全在 angular.

  5. 之外

编辑添加:

  1. (侦听容器 "click" 事件并过滤它是否来自锚点)
    参见@cyrix 的

实现此功能的正确方法是什么?

编辑更新:
我接受了作为 "best" 选项的答案,但如果有人发现或他们发布了 "Angular" 方法来做到这一点,请添加一个答案。

我遇到了同样的问题,通过创建自定义指令并检查每次点击是否目标是锚元素,向动态内容的容器添加一个 click-listener 来解决这个问题。如果它是锚元素,则阻止默认行为并采用 href 属性,将其用作 router.navigateByUrl.

的 url
private onClick(e: any) {
    let link = this.checkForParentLink(e.target as HTMLElement);
    if(link && link.getAttribute('href')) {
      let href = link.getAttribute('href');
      let isMailOrPhone = href.startsWith('mailto:') || href.startsWith('tel:');
      if(isMailOrPhone) return;
      e.preventDefault();
      if(link.getAttribute('target') === '_blank') {     
        let win = window.open(href, '_blank');
        win && win.focus();
      } else {
        this.router.navigateByUrl(href);
      }
    }
  }

  private checkForParentLink(element: HTMLElement): HTMLLinkElement {
    if(!element) return;
    if(element.tagName === 'A') {
      return element as HTMLLinkElement;
    // this.element.nativeElement is in this case the container element
    }
    if(element.parentNode === this.element.nativeElement) {
      return null;
    }
    return this.checkForParentLink(element.parentNode as HTMLElement);
  }