1- import { Injectable , Optional , SkipSelf } from '@angular/core' ;
1+
2+ import { Inject , Injectable , Optional , SkipSelf } from '@angular/core' ;
23import { HttpClient } from '@angular/common/http' ;
34
45import { Observable } from 'rxjs/Observable' ;
@@ -8,57 +9,64 @@ import 'rxjs/add/operator/do';
89import 'rxjs/add/operator/finally' ;
910import 'rxjs/add/operator/map' ;
1011import 'rxjs/add/operator/share' ;
12+ import 'rxjs/observable/throw' ;
1113
1214
1315@Injectable ( )
1416export class SvgIconRegistryService {
1517
16- private iconsByUrl = new Map < string , SVGElement > ( ) ;
17- private iconsLoadingByUrl = new Map < string , Observable < SVGElement > > ( ) ;
18-
19- constructor ( private http :HttpClient ) {
20- }
18+ private iconsByUrl = new Map < string , SVGElement > ( ) ;
19+ private iconsLoadingByUrl = new Map < string , Observable < SVGElement > > ( ) ;
2120
22- loadSvg ( url :string ) : Observable < SVGElement > {
21+ constructor ( private http : HttpClient , private fallbackIconUrl : string ) {
22+ }
2323
24- if ( this . iconsByUrl . has ( url ) ) {
25- return Observable . of ( this . iconsByUrl . get ( url ) ) ;
26- } else if ( this . iconsLoadingByUrl . has ( url ) ) {
27- return this . iconsLoadingByUrl . get ( url ) ;
28- } else {
29- const o = < Observable < SVGElement > > this . http . get ( url , { responseType : 'text' } )
30- . map ( svg => {
31- const div = document . createElement ( 'DIV' ) ;
32- div . innerHTML = svg ;
33- return < SVGElement > div . querySelector ( 'svg' ) ;
34- } )
35- . do ( svg => {
36- this . iconsByUrl . set ( url , svg ) ;
37- } )
38- . finally ( ( ) => {
39- this . iconsLoadingByUrl . delete ( url ) ;
40- } )
41- . share ( ) ;
24+ loadSvg ( url : string ) : Observable < SVGElement > {
25+ if ( this . iconsByUrl . has ( url ) ) {
26+ return Observable . of ( this . iconsByUrl . get ( url ) ) ;
27+ } else if ( this . iconsLoadingByUrl . has ( url ) ) {
28+ return this . iconsLoadingByUrl . get ( url ) ;
29+ } else {
30+ const o = this . http . get ( url , { responseType : 'text' } )
31+ . map ( svg => {
32+ const div = document . createElement ( 'DIV' ) ;
33+ div . innerHTML = svg ;
34+ return < SVGElement > div . querySelector ( 'svg' ) ;
35+ } )
36+ . catch ( ( error ) => {
37+ if ( this . fallbackIconUrl ) {
38+ return this . loadSvg ( this . fallbackIconUrl ) ;
39+ } else {
40+ return Observable . throw ( error ) ;
41+ }
42+ } )
43+ . do ( svg => {
44+ this . iconsByUrl . set ( url , svg ) ;
45+ } )
46+ . finally ( ( ) => {
47+ this . iconsLoadingByUrl . delete ( url ) ;
48+ } )
49+ . share ( ) ;
50+ this . iconsLoadingByUrl . set ( url , o ) ;
51+ return o ;
52+ }
4253
43- this . iconsLoadingByUrl . set ( url , o ) ;
44- return o ;
45- }
46- }
54+ }
4755
48- unloadSvg ( url :string ) {
49- if ( this . iconsByUrl . has ( url ) ) {
50- this . iconsByUrl . delete ( url ) ;
51- }
52- }
56+ unloadSvg ( url : string ) {
57+ if ( this . iconsByUrl . has ( url ) ) {
58+ this . iconsByUrl . delete ( url ) ;
59+ }
60+ }
5361
5462}
5563
56- export function SVG_ICON_REGISTRY_PROVIDER_FACTORY ( parentRegistry :SvgIconRegistryService , http :HttpClient ) {
57- return parentRegistry || new SvgIconRegistryService ( http ) ;
64+ export function SVG_ICON_REGISTRY_PROVIDER_FACTORY ( parentRegistry : SvgIconRegistryService , http : HttpClient , fallBackIconUrl : string ) {
65+ return parentRegistry || new SvgIconRegistryService ( http , fallBackIconUrl ) ;
5866}
5967
6068export const SVG_ICON_REGISTRY_PROVIDER = {
61- provide : SvgIconRegistryService ,
62- deps : [ [ new Optional ( ) , new SkipSelf ( ) , SvgIconRegistryService ] , HttpClient ] ,
63- useFactory : SVG_ICON_REGISTRY_PROVIDER_FACTORY
69+ provide : SvgIconRegistryService ,
70+ deps : [ [ new Optional ( ) , new SkipSelf ( ) , SvgIconRegistryService ] , HttpClient , [ new Inject ( 'FALLBACK_ICON' ) ] ] ,
71+ useFactory : SVG_ICON_REGISTRY_PROVIDER_FACTORY ,
6472} ;
0 commit comments