Tobi
Tobi

Reputation: 2040

Angular material svg icon cannot be loaded due to parsing error

I am trying to load a custom svg icon with angular material 7.2.0 and
angular v7.2.0

Therefore, I register the icon like

iconRegistry.addSvgIcon('box',
  sanitizer.bypassSecurityTrustResourceUrl('assets/box.svg'));

Then I use the icon as

<mat-icon  svgIcon="box"></mat-icon>

but the icon is not showing.
In the console I can see the error Error retrieving icon: Http failure during parsing for http://localhost:4200/assets/box.svg.

I checked the code where the error is thrown and there I can see, that the error occurs in the stream returned from iconRegistry.getNamedSvgIcon, so I added the following code after registering the icon:

iconRegistry.getNamedSvgIcon('box')
.subscribe(res => console.log(res), err => console.error(err))

Now I can see, that the actual error contains Unexpected token < in JSON at position 0, so it seems that angular is trying to parse the SVG as Json.

Is this a bug or did I misconfigure something? I also checked the headers of the response and the content type for SVG is correct.

Upvotes: 1

Views: 4121

Answers (2)

Mahdi
Mahdi

Reputation: 755

For SSR, full URL is needed in order to retrieve svg icon. When encountered to this issue, I fixed it with something like this:

import {Component, OnInit, Inject} from '@angular/core';
import {MatIconRegistry} from '@angular/material';
import {DomSanitizer} from '@angular/platform-browser';
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  constructor(private _matIconRegistry: MatIconRegistry, private _domSanitizer: DomSanitizer, @Inject(PLATFORM_ID) private platformId: string, @Optional() @Inject(REQUEST) protected request: Request) {
    const svgUrl = 'assets/Icons/loader-default.svg';
    // domain and port for SSR in this example is static. Use i.e. environment files to use appropriate dev/prod domain:port
    const domain = request && isPlatformServer(platformId) ?
  `${request.protocol}:${request.get('host')}/` : ''; 
    this._matIconRegistry.addSvgIcon('loader', this._domSanitizer.bypassSecurityTrustResourceUrl(domain + svgUrl));
  }

  ngOnInit() {
  }

}

Upvotes: 0

Md. Imrul Islam
Md. Imrul Islam

Reputation: 318

I have just modify your code,

The addSvgIcon registers our icon by taking-in 2 arguments, the first one being the icon label which is of type string.

The second argument is the relative URL path pointing to the location of the icon. This is of type SafeResourceUrl. To parse the url path string into SafeResourceUrl, we can make use of the DomSanitizer provided by Angular.

import

import { MatIconRegistry } from "@angular/material/icon";
import { DomSanitizer } from "@angular/platform-browser";

In constructor

  constructor(
    private matIconRegistry: MatIconRegistry,
    private domSanitizer: DomSanitizer
  ) {
     this.matIconRegistry.addSvgIcon(
     "meeting",
    this.domSanitizer.bypassSecurityTrustResourceUrl("../assets/meetingicon.svg")
    );
  }

Html

<mat-icon svgIcon="meeting"></mat-icon>

Upvotes: 3

Related Questions