Angular2 SVG xlink:href
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.
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 svgconst 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)) } }}
I think it can be solved using angular pipe feature.
<use attr.xlink:href={{weatherData.currently.icon|iconpipe}}></use>
ExplanationThis pipe will
- Pass the parsed response value to the pipe
- Return the complete svg path
attr.xlink:href=
will get the expected path & svg will rendered inhtml page
here is pipe typescript code
import { PipeTransform, Pipe } from '@angular/core';@Pipe({ name: 'iconpipe'})export class IconPipe implements PipeTransform { constructor() { } transform(value: any) { let properIconName = undefined; switch (value) { case 'clear-day': properIconName = '/assets/images/weather-SVG-sprite.svg#sun'; break; case 'clear-night': properIconName = '/assets/images/weather-SVG-sprite.svg#night-1'; break; case 'partly-cloudy-day': properIconName = '/assets/images/weather-SVG-sprite.svg#cloudy'; break; case 'partly-cloudy-night': properIconName = '/assets/images/weather-SVG-sprite.svg#night'; break; case 'cloudy': properIconName = '/assets/images/weather-SVG-sprite.svg#cloud'; break; case 'rain': properIconName = '/assets/images/weather-SVG-sprite.svg#rain'; break; case 'sleet': properIconName = '/assets/images/weather-SVG-sprite.svg#snowflake'; break; case 'snow': properIconName = '/assets/images/weather-SVG-sprite.svg#snowing'; break; case 'wind': properIconName = '/assets/images/weather-SVG-sprite.svg#storm'; break; case 'fog': properIconName = '/assets/images/weather-SVG-sprite.svg#sun'; break; case 'humid': properIconName = '/assets/images/weather-SVG-sprite.svg#sun'; break; default: properIconName = '/assets/images/weather-SVG-sprite.svg#summer'; } return properIconName; }}