是否可以使用角度插值来显示角度分量?

问题描述 投票:0回答:1

我有一个我依赖的 Angular 组件。该组件有一个getData方法,那么在该组件的模板中调用该方法,并使用Angular插值显示结果。现在我有一个覆盖该方法的子组件。所以我需要从这个子组件返回一个自定义的 html 字符串。

目前我正在将 html 字符串作为输入传递给该组件。但我在用这种方法使用 JavaScript 时遇到了麻烦,而且它不太灵活。

这是代码的简化版本:

@Component({
  selector: 'app-parent',
  template: "
    <div>
      Parent Component:
      <div>{{ getData() }}</div>
    </div>
  "
})
export class ParentComponent {
  getData(): string {
    return ''; // This will be overridden by the child component
  }
}

@Component({
  template: '',
})
export class ChildComponent extends ParentComponent {
  getData(): string {
    return '<h2>My Title</h2>'; // Custom HTML string
  }
}

我可以输入代码吗

<h2>My Title</h2>
进入自定义组件并返回该组件而不是返回 html 字符串。请注意,我无法更改 ParentComponent 的工作方式。

angular angular-components string-interpolation angular-template
1个回答
0
投票

在 Angular 中,插值 ({{ }}) 用于将组件类属性绑定到组件模板中的文本节点。这意味着您不能直接使用插值来插入或渲染 HTML 元素或 Angular 组件。插值将任何值视为字符串,因此如果您尝试将 HTML 或组件选择器作为字符串返回,Angular 会将其转义以防止 XSS(跨站脚本)等安全问题,并且它将在 DOM 中呈现为纯文本.

鉴于您所描述的约束,您无法更改 ParentComponent 实现,但希望从 ChildComponent 返回自定义 HTML 或 Angular 组件,您将面临限制,因为 Angular 不支持直接通过渲染组件或 HTML以这种方式插值。

但是,还有其他方法可以在 Angular 应用程序中动态渲染组件或 HTML,尽管它们可能不适用于无法更改 ParentComponent 的特定约束。其中包括:

使用 Angular 的 DomSanitizer 进行安全 HTML 绑定: 如果您只需要插入 HTML(而不是 Angular 组件),则可以使用 Angular 的 [innerHTML] 绑定来安全地插入 HTML 内容。您需要使用 Angular 的 DomSanitizer 清理 HTML 内容以绕过安全检查。这并不直接适用于您的场景,因为ParentComponent的模板无法更改。

动态组件加载: Angular 提供了使用 ViewContainerRefComponentFactoryResolver 在运行时动态加载组件的机制。这种方法允许更复杂的组件插入场景,但需要占位符指令或父组件模板中的已知插入点,这在您的情况下似乎不是一个选项。

考虑到您的限制,Angular 的设计不支持您正在寻求的最直接的方法(直接从方法返回组件并通过插值渲染它)。

一个潜在的解决方法虽然并不理想,并且取决于您的完整应用程序上下文,但可能是重新评估解决方案的架构。考虑是否:

如果涉及数据获取或处理,getData() 中的逻辑可以移动到服务中,从而允许不同的组件以独特的方式对此数据做出反应。 子组件可以使用 ng-content 或模板出口将内容投影到父组件中,尽管这需要更改父组件的结构。 在您被锁定到特定架构而无法更改父组件的情况下,最好的行动方案可能是重新考虑组件之间的交互模式,或者诉诸于在 Angular 上下文之外使用本机 JavaScript 解决方案,这来自有其自身的一系列挑战,通常不推荐。

动态 HTML 内容指令 下面介绍了如何设置指令来动态插入 HTML。这假设您有某种方法可以在模板中的所需位置应用此指令。

// dynamic-html.directive.ts
import { Directive, Input, ElementRef, OnInit, Renderer2, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Directive({
  selector: '[appDynamicHtml]'
})
export class DynamicHtmlDirective implements OnInit {
  @Input() appDynamicHtml: string;

  constructor(private elementRef: ElementRef, private renderer: Renderer2, private sanitizer: DomSanitizer) {}

  ngOnInit(): void {
    const sanitizedHtml = this.sanitizer.sanitize(SecurityContext.HTML, this.appDynamicHtml);
    if (sanitizedHtml) {
      this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', sanitizedHtml);
    }
  }
}

应用指令 假设您可以向 ParentComponent 的模板添加指令(您提到的不可能),则该指令将按如下方式使用:

<!-- In parent or child component template -->
<div appDynamicHtml="{{ getData() }}"></div>
© www.soinside.com 2019 - 2024. All rights reserved.