简体   繁体   English

Angular Universal / SSR nativeElement.innerHTML 和 renderer.setProperty 抛出错误:NotYetImplemented

[英]Angular Universal / SSR nativeElement.innerHTML and renderer.setProperty throws Error: NotYetImplemented

I have below component to render svg icons:我有以下组件来呈现 svg 图标:

Component成分

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;
  }
}

Template模板

<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>

This works fine in browser but throws below error in Angular Universal/SSR.这在浏览器中运行良好,但在 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)

I have also tried it with renderer.setProperty , but even that doesnt work and throws below error:我也用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)

Can anyone please guide how to fix this and make it work on server/ssr?谁能指导如何解决此问题并使其在服务器/ssr 上运行?

This is related to the Domino which doesn't implement innerHTML setter.这与不实现innerHTML setter 的 Domino 有关。

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

The simplest way to fix this is either by having the svgs defined in css class or svg as assets files and swap either the url or css class to change the icon from the component. The simplest way to fix this is either by having the svgs defined in css class or svg as assets files and swap either the url or css class to change the icon from the component.

So I don't know if this is performant but it works for me.所以我不知道这是否有效,但它对我有用。

    const innerHTMLString = '<div>Your html</div>';
    const innerHTML = this.domSanitizer.sanitize(
      SecurityContext.HTML,
      this.domSanitizer.bypassSecurityTrustHtml(innerHTMLString)
    );

    if(isPlatformServer(this.platformId)) {
      // .innerHTML is not supported by SSR
      const innerElement = this.renderer.createElement('ng-container');
      this.renderer.appendChild(this.el.nativeElement, innerElement);
      this.renderer.setProperty(innerElement, 'outerHTML', innerHTML);
      this.renderer.removeChild(this.el.nativeElement, innerElement);
    } else {
      this.el.nativeElement.innerHTML = innerHTML;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM