Skip to content

Instantly share code, notes, and snippets.

@pjlamb12
Last active December 7, 2020 23:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjlamb12/b265ce3cf741d0237c084a27ea553dda to your computer and use it in GitHub Desktop.
Save pjlamb12/b265ce3cf741d0237c084a27ea553dda to your computer and use it in GitHub Desktop.
SVG Icon Manager Module for Angular using the angular-svg-icon library
@NgModule({
imports: [
IconManagerModule.forRoot({ configUrl: './assets/icons/heroicons.json' }),
]
})
export class AppModule {}
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SvgIconManagerService } from './svg-icon-manager/svg-icon-manager.service';
import { SvgIconManagerConfig } from './svg-icon-manager/svg-icon-config.class';
export function initConfig(svgSvc: SvgIconManagerService) {
return () => svgSvc.loadConfig();
}
@NgModule({
imports: [CommonModule],
providers: [
SvgIconManagerService,
{
provide: APP_INITIALIZER,
useFactory: initConfig,
deps: [SvgIconManagerService],
multi: true,
},
],
})
export class IconManagerModule {
static forRoot(config: SvgIconManagerConfig): ModuleWithProviders<IconManagerModule> {
return {
ngModule: IconManagerModule,
providers: [
{
provide: SvgIconManagerConfig,
useValue: config,
},
SvgIconManagerService,
],
};
}
}
export interface IconImageFile {
iconName: string;
iconPath: string;
}
export interface CustomIconData {
iconName: string;
iconData: string;
}
export class SvgIconManagerConfig {
configUrl: string;
constructor() {}
}
import { waitForAsync } from '@angular/core/testing';
import { of } from 'rxjs';
import { SvgIconManagerService } from './svg-icon-manager.service';
const DEMO_ICONS_JSON = {
iconImageFiles: [
{
iconName: 'badge-check',
iconPath: '/assets/icons/badge-check.svg',
},
],
customIcons: [
{
iconName: 'academic-cap',
iconData:
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path d="M10.394 2.08a1 1 0 00-.788 0l-7 3a1 1 0 000 1.84L5.25 8.051a.999.999 0 01.356-.257l4-1.714a1 1 0 11.788 1.838L7.667 9.088l1.94.831a1 1 0 00.787 0l7-3a1 1 0 000-1.838l-7-3zM3.31 9.397L5 10.12v4.102a8.969 8.969 0 00-1.05-.174 1 1 0 01-.89-.89 11.115 11.115 0 01.25-3.762zM9.3 16.573A9.026 9.026 0 007 14.935v-3.957l1.818.78a3 3 0 002.364 0l5.508-2.361a11.026 11.026 0 01.25 3.762 1 1 0 01-.89.89 8.968 8.968 0 00-5.35 2.524 1 1 0 01-1.4 0zM6 18a1 1 0 001-1v-2.065a8.935 8.935 0 00-2-.712V17a1 1 0 001 1z" /> </svg>',
},
],
};
describe('SvgIconManagerService', () => {
let service: SvgIconManagerService;
let mockHttpClient;
let mockConfig;
let mockSvgIconRegistryService;
beforeEach(() => {
mockHttpClient = {
get: null,
};
mockSvgIconRegistryService = {
loadSvg: jest.fn().mockReturnValue(of(null)),
addSvg: jest.fn(),
};
service = new AngularSvgIconPreloaderService(
mockHttpClient,
mockConfig,
mockSvgIconRegistryService
);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it(
'should call the load icons method',
waitForAsync(() => {
mockHttpClient.get = jest.fn().mockReturnValue(of(DEMO_ICONS_JSON));
service.loadConfig();
expect(mockSvgIconRegistryService.loadSvg).toHaveBeenCalled(); // fails
})
);
});
import { Injectable, Optional } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { SvgIconManagerConfig } from './svg-icon-config.class';
import { SvgIconRegistryService } from 'angular-svg-icon';
import { CustomIconData, IconImageFile } from './icon.interface';
import { take } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class SvgIconManagerService {
private configUrl: string = './assets/icons.json';
private iconsFileDate: { iconImageFiles: IconImageFile[]; customIcons: CustomIconData[] };
public configSubject: Subject<any> = new Subject<any>();
constructor(
private _http: HttpClient,
@Optional() config: SvgIconManagerConfig,
private _iconRegistry: SvgIconRegistryService,
) {
if (config) {
this.configUrl = config.configUrl;
}
}
loadConfig(): Promise<any> {
return this._http
.get(this.configUrl)
.toPromise()
.then((configData: { iconImageFiles: IconImageFile[]; customIcons: CustomIconData[] }) => {
this.iconsFileDate = configData;
this.loadIcons();
})
.catch((err: any) => {
this.iconsFileDate = { customIcons: [], iconImageFiles: [] };
this.loadIcons();
});
}
loadIcons() {
this.iconsFileDate.iconImageFiles.forEach((i: IconImageFile) => {
this._iconRegistry.loadSvg(i.iconPath, i.iconName).pipe(take(1)).subscribe();
});
this.iconsFileDate.customIcons.forEach((i: CustomIconData) => {
this._iconRegistry.addSvg(i.iconName, i.iconData);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment