与用户创建的内容进行数据绑定/交互



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

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

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

  2. (DOM操作)
    在用户创建的内容<a href="/path/to/diffrent/page/in/app">中保留适当的HTML。然后在绑定到innerHTML之后,获取一个ElementRef,然后找到每个锚点标记并覆盖click事件。这种DOM操作在角度上似乎非常令人沮丧。

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

编辑添加:

  1. (监听容器"点击"事件并过滤它是否来自锚点)
    查看@cyrix的答案

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

编辑更新:
我接受了一个答案作为"最佳"选项,但如果有人找到或发布了一种"角度"方法,请添加一个答案。

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

最新更新