Angular: Dynamically inserting SVG into an element
I recently launched a single-page web app for a digital illustrator. The app was pretty standard, but they asked a unique request. The author did not want me to create renditions of their work in BPM, PNG, or JPEG formats. Instead, they wanted me to store and deliver SVG data from a database dynamically. Think, Base64 images but for vector-based artwork.
On the database side, it's nothing to complex. I chose Firebase as my real-time backend, but the rest of this entry will show you a few different ways on how to render SVG using Angular.
Getting Started
Here is an example of SVG content.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
xml:space="preserve">
<ellipse fill="#C6C6C6" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path id="bird" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
C434.693,207.929,439.613,203.01,445.731,203.01z"/>
</svg>
Method #1 - Angular Decorators
This method uses experimental support for decorators. The Angular CLI will tell you that it's experimental and may change.
HTML
Place a div within your name.component.html
.
<div #dataContainer></div>
Component
Place this within your name.component.ts
.
import { Component, OnInit } from '@angular/core';
import { ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
@ViewChild('dataContainer') dataContainer: ElementRef;
constructor() { }
ngOnInit() {
svg = "SVG CONTENT"
this.dataContainer.nativeElement.innerHTML = svg;
})
}
}
Method #2 - [innerHTML]
Place this within your name.component.ts
.
<div class="svg" [innerHTML]="svg"></div>
Place this within your name.component.ts
.
import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
svg:SafeHtml;
constructor(private sanitizer: DomSanitizer) { }
ngOnInit() {
this.svg = this.sanitizer.bypassSecurityTrustHtml("‹‹ SVG CONTENT ››");
})
}
}
Method 3 - Use a Plugin
This method works best if you have a static SVG file that you want to load dynamically. The two ways above are ideal if you're going to store the actual SVG data within a database.
Install ng-inline-svg
.
npm install ng-inline-svg
Place this within your name.component.html
.
<div [inlineSVG]="svg"></div>
Place this within your app.module.ts
.
import { InlineSVGModule } from 'ng-inline-svg';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, InlineSVGModule],
bootstrap: [AppComponent]
})
class AppModule {}