首页 > 解决方案 > Angular Universal / SSR nativeElement.innerHTML 和 renderer.setProperty 抛出错误:NotYetImplemented

问题描述

我有以下组件来呈现 svg 图标:

零件

import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild } from '@angular/core';

@Component({
  selector: 'icon-svg',
  templateUrl: './icon-svg.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class IconSVGComponent {
  @ViewChild('svgElement', { static: false }) svgElement: ElementRef;

  @Input() icon: string;
  @Input() fill: string = 'currentColor';
  @Input() width: number = null;
  @Input() height: number = null;
  @Input() alt: string;

  public svg: string;

  public viewBox = "0 0 24 24";

  constructor() {
  }

  ngOnInit() {
    let icons = {
      'business': { value: '<path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z" />' },
      'person': { value: '<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />' },
      'menu': { value: '<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />' },
      'search': { value: '<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />' },
      'close': { value: '<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />' }
    };

    let icon = icons[this.icon].value;
    if (icon) {
      this.svg = icon;
      if (this.icon == 'facebook' || this.icon == 'linkedin' || this.icon == 'twitter' || this.icon == 'whatsapp') {
        this.viewBox = "0 0 512 512";
      }
    }
  }

  ngAfterViewInit() {
    this.svgElement.nativeElement.innerHTML = this.svg;
  }
}

模板

<svg xmlns="http://www.w3.org/2000/svg" [attr.fill]="fill" [attr.viewBox]="viewBox" [attr.width]="width" [attr.height]="height" class="svg-icon" #svgElement>
</svg>

这在浏览器中运行良好,但在 Angular Universal/SSR 中引发以下错误。

Error: NotYetImplemented
    at Element.Wo4J.exports.nyi (D:\ClientApp\dist-server\main.js:1:1616260)
    at IconSVGComponent.ngAfterViewInit (D:\ClientApp\dist-server\main.js:1:3046674)

我也试过了renderer.setProperty,但即使这样也不起作用并抛出以下错误:

Error: NotYetImplemented
    at Element.Wo4J.exports.nyi (D:\ClientApp\dist-server\main.js:1:1616260)
    at platform_server_DefaultServerRenderer2.setProperty (D:\ClientApp\dist-server\main.js:1:1264487)
    at BaseAnimationRenderer.setProperty (D:\ClientApp\dist-server\main.js:1:1527203)
    at IconSVGComponent.ngAfterViewInit (D:\ClientApp\dist-server\main.js:1:3046680)

谁能指导如何解决这个问题并让它在服务器/ssr上工作?

标签: angularangular-universal

解决方案


这与不实现innerHTMLsetter 的 Domino 有关。

https://github.com/fgnass/domino/blob/12a5f67136a0ac10e3fa1649b8787ba3b309e9a7/lib/Element.js#L95

解决此问题的最简单方法是将 svg 在 css 类或 svg 中定义为资产文件,然后交换 url 或 css 类以更改组件中的图标。


推荐阅读