'How do I import svg from file to a component in angular 5?

All tutorials with adding svg to a component in AngularCli that I found recommend to insert it in html template, something like this:

<div>
  <svg viewBox="0 0 250 250">
    <svg:g class="group">
       <svg:polygon class="shield" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2" />
       <svg:path class="a" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1
      L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
    </svg:g>
  </svg>
</div>

But I wish to keep templates clear and instert only few tags in it with url to separated svg file, somwehow like this:

<svg class="star">
        <use xlink:href="../../../assets/images/svg/star.svg"
               x="0"
               y="0" />
</svg>

Ho do I use separated svg files in components?



Solution 1:[1]

Include your SVG files in src/assets folder and add the svg folder in your angular.json file.

"assets": [ "src/assets/svg/*" ]

This way you can include the file in your components as you wish.

Solution 2:[2]

If you have logo.svg:

  1. Put it inside your src/assets folder
  2. Include folder in the angular.json config: "assets": [ "src/assets" ]
  3. Refer to it from template: <img src="assets/svg/logo.svg">

Solution 3:[3]

one way to do this is to set id property for your svg file and put your svg files in your asset folder. then use that id in mat-icon like this:

<mat-icon svgIcon="my-star-icon"></mat-icon>

this is a better way to do it; in this way you don't have to deal with svg tags in your UI html code. also this supports google icons.

though this works if you're using angular material.

Edit: You need to register the icon with the IconRegistry in your component for this to work:

  constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
    iconRegistry.addSvgIcon(
        'my-star-icon',
        sanitizer.bypassSecurityTrustResourceUrl('assets/icons/my-star-icon.svg'));
  }

Check the docs here and an example here.

Solution 4:[4]

So I was trying to do this, and for the life of me i could not get this svg to show up until.... After many internet searches, and I don't think it's just me and if you copy pasta path from the internet then maybe you forgot to include this

xmlns="http://www.w3.org/2000/svg"

<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100">
<path d="I love copying and pasting paths"/>
</svg>

Then you can go ahead and do your

 <img src="assets/img/logo.svg" />

and if this doesn't work and somehow you want to work with images instead then put your images in

assets/img/copypasta.png

Solution 5:[5]

There is a more elegant way, however it implies that the svg file has the same ID as the file name.

Svg component:

import { Component, Input, OnInit } from '@angular/core';

@Component({
  selector: 'app-svg-icon',
  template: '
    <svg attr.width="{{width}}px" attr.height="{{height}}px" attr.fill="{{fill}}" attr.class="{{class}}">
      <use attr.xlink:href="assets/icons/{{icon}}.svg#{{icon}}"></use>
    </svg>
  ',
})
export class SvgIconComponent implements OnInit {
  @Input() icon!: string;
  @Input() width?: number;
  @Input() height?: number;
  @Input() size?: number = 24;
  @Input() fill?: string;
  @Input() class?: string;

  ngOnInit(): void {
    if (!this.width || !this.height) {
      this.width = this.size;
      this.height = this.size;
    }
  }
}

Let's say you have svg in a folder: /assets/icons/person.svg

The svg itself contains the following code (So that you can easily change the size and color of your svg, it should not contain height, width and fill attributes):

<svg id="person" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z" />
</svg>

And now you can use your icon in any component:

<app-svg-icon [icon]="'person'" fill="red" [size]="48"></app-svg-icon>

Solution 6:[6]

TL;DR, use HttpClient to fetch for the file, then use bypassSecurityTrustHtml to render it with [innerHTML].

This may be a bit late for an answer, but here's how we found the solution. we tried looking up into how angular material does it for their icons, and boy were we surprised to how simple it really is. They were just fetching the file using HttpClient! It was already at the back of our minds but we kept ignoring it cause we thought maybe there was a better solution.

So after a few minutes of searching, we stumbled upon this: https://github.com/angular/components/blob/653457eaf48faab99227f37bc2fe104d9f308787/src/material/icon/icon-registry.ts#L621

So basically, if you have your SVG file somewhere in your assets folder (/assets/images/svg/star.svg), all you have to do is to fetch it using HttpClient.get and use the DomSanitizer to bypass security and trust the given value to be safe HTML before you can render it to your component.

And finally, here's how our component looks like:

import { Component, OnInit, SecurityContext } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';

@Component({
  selector: 'app-svg-icon',
  template: `<span [innerHTML]="svgIcon"></span>`,
  styleUrls: ['./svg-icon.component.scss'],
})
export class SvgIconComponent implements OnInit {

  @Input()
  public name?: string;

  public svgIcon: any;

  constructor(
    private httpClient: HttpClient,
    private sanitizer: DomSanitizer,
    ) {
  }

  public ngOnInit(): void {
    this.httpClient
      .get(`assets/images/svg/${this.name}.svg`, { responseType: 'text' })
      .subscribe(value => {
        this.svgIcon = this.sanitizer.bypassSecurityTrustHtml(value);
      });
  }

}

Now you can just import the component anywhere in your app as

<app-svg-icon name="star"></app-svg-icon>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mr_blond
Solution 2 Boris Yakubchik
Solution 3 Daniel
Solution 4 Dharman
Solution 5
Solution 6