【问题标题】:Databinding/interaction with user created content与用户创建的内容的数据绑定/交互
【发布时间】:2018-03-28 07:57:19
【问题描述】:

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

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

  1. (带有 JIT 编译器的动态组件)
    用户创建的内容将具有像<a [routerLink]="/path/to/diffrent/page/in/app"> 这样的角度语法。然后使用示例here 加载带有JitCompilerFactory 和自定义装饰器的运行时编译器,以保留组件和模块元数据,以将用户创建的内容作为模板进行JIT 编译组件。然而,对于构建优化器,这需要restoring the ctorParameters。有了这个,您不会获得 AOT 的所有大小优势,因为您仍然需要加载 JIT 编译器,并且如 here 所述 - “ 而且这似乎是有风险的,因为编译器会受到内部变化的影响。它适用于@angular/compiler@4.4.5,但可能不适用于其他版本。”

  2. (DOM 操作)
    在用户创建的内容<a href="/path/to/diffrent/page/in/app"> 中保留正确的 HTML。然后绑定到innerHTML 后得到一个ElementRef,然后找到每个锚标签并覆盖点击事件。这种 DOM 操作在 Angular 中似乎非常不受欢迎。

  3. (自定义窗口事件)
    用户创建的内容将类似于<a onclick="window.someGlobalFunc("/path/to/diffrent/page/in/app")">。然后以某种方式以角度收听窗口事件。我更不喜欢这个想法,因为它完全超出了角度。

编辑添加:

  1. (监听容器“点击”事件并过滤是否来自锚点)
    见@cyrix 的answer

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

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

【问题讨论】:

  • 让 Angular “东西”在动态添加的内容中工作的唯一方法是在运行时编译组件并动态添加该组件。您始终可以使用命令式方法 (JavaScript) 访问和修改 DOM 以及添加/删除事件处理程序。
  • @GünterZöchbauer 是的,这是我的解决方案 1。但这需要“黑客”,这些“黑客”可能会发生变化,以便与 AOT 和构建优化器一起使用。
  • 找到了这个SO,其中@GünterZöchbauer 链接到这个,Angular 2 dynamic tabs with user-click chosen components 这导致找到这个作为可能的解决方案。 Insert component into html dynamically
  • @ttugates here 提到的“较少角度的方式”是我的解决方案#2。 "Angular 2 dynamic tabs with user-click chosen components" 使用 ComponentFactoryResolver 要求组件已经存在(被编译)。 ngComponentOutlet 解决方案here 只解决了如何将组件添加到视图中。

标签: javascript html angular angular-cli angular2-aot


【解决方案1】:

我遇到了同样的问题,并通过创建自定义指令并检查每次点击是否目标是锚元素,将click-listener 添加到动态内容的容器中来解决它。如果它是一个锚元素,阻止默认行为并采用href-attribute,将其用作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);
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    相关资源
    最近更新 更多