Angular2 SVG xlink:href
Solution 1:
SVG elements doen't have properties, therefore attribute binding is required most of the time (see also Properties and Attributes in HTML).
For attribute binding you need
<use [attr.xlink:href]="iconHref">
or
<use attr.xlink:href="{{iconHref}}">
Update
Sanitization might cause issues.
See also
- https://github.com/angular/angular/issues/9510)
- https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizationService-class.html
Update DomSanitizationService
is going to be renamed to DomSanitizer
in RC.6
Update this should be fixed
but there is an open issue to support this for namespaced attributes https://github.com/angular/angular/pull/6363/files
As work-around add an additional
xlink:href=""
Angular can update the attribute but has issues with adding.
If xlink:href
is actually a property then your syntax should work after the PR was added as well.
Solution 2:
I was still having issues with the attr.xlink:href described by Gunter so I created a directive that is similar to SVG 4 Everybody but is specific for angular2.
Usage
<div [useLoader]="'icons/icons.svg#menu-dashboard'"></div>
Explanation
This directive will
- Load icons/icons.svg over http
- Parse the response and extract path info for #menu-dashboard
- Add the parsed svg icon to the html
Code
import { Directive, Input, ElementRef, OnChanges } from '@angular/core';
import { Http } from '@angular/http';
// Extract necessary symbol information
// Return text of specified svg
const extractSymbol = (svg, name) => {
return svg.split('<symbol')
.filter((def: string) => def.includes(name))
.map((def) => def.split('</symbol>')[0])
.map((def) => '<svg ' + def + '</svg>')
}
@Directive({
selector: '[useLoader]'
})
export class UseLoaderDirective implements OnChanges {
@Input() useLoader: string;
constructor (
private element: ElementRef,
private http: Http
) {}
ngOnChanges (values) {
if (
values.useLoader.currentValue &&
values.useLoader.currentValue.includes('#')
) {
// The resource url of the svg
const src = values.useLoader.currentValue.split('#')[0];
// The id of the symbol definition
const name = values.useLoader.currentValue.split('#')[1];
// Load the src
// Extract interested svg
// Add svg to the element
this.http.get(src)
.map(res => res.text())
.map(svg => extractSymbol(svg, name))
.toPromise()
.then(svg => this.element.nativeElement.innerHTML = svg)
.catch(err => console.log(err))
}
}
}