Skip to content
This repository has been archived by the owner on Dec 10, 2022. It is now read-only.

Commit

Permalink
feat(preset): Implement basic preset module
Browse files Browse the repository at this point in the history
  • Loading branch information
gund committed Dec 30, 2017
1 parent f816584 commit 5503e68
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/preset/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export { PresetType } from './preset-token';
export * from './preset-method';
export * from './preset.service';
export * from './preset.module';
export * from './preset-default.module';
15 changes: 15 additions & 0 deletions src/preset/preset-default.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';

import { createWithPresetMethodFor } from './preset-method';
import { PresetService } from './preset.service';

@NgModule({
imports: [CommonModule],
exports: [],
declarations: [],
providers: [PresetService],
})
export class PresetDefaultModule {
static withPreset = createWithPresetMethodFor(PresetDefaultModule);
}
15 changes: 15 additions & 0 deletions src/preset/preset-method.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ANALYZE_FOR_ENTRY_COMPONENTS, ModuleWithProviders, Type } from '@angular/core';

import { PRESET_TYPES_TOKEN, PresetType } from './preset-token';

export function createWithPresetMethodFor<T = any>(moduleClass: Type<any>) {
return (presetType: PresetType<T>): ModuleWithProviders => {
return {
ngModule: moduleClass,
providers: [
{ provide: PRESET_TYPES_TOKEN, useValue: presetType, multi: true },
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: presetType, multi: true },
],
};
};
}
6 changes: 6 additions & 0 deletions src/preset/preset-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { InjectionToken, Type } from '@angular/core';

// tslint:disable-next-line:no-empty-interface
export interface PresetType<T = any> extends Type<T> { }

export const PRESET_TYPES_TOKEN = new InjectionToken<PresetType[]>('PresetTypes');
9 changes: 6 additions & 3 deletions src/preset/preset.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';

import { PresetService } from './preset.service';

@NgModule({
imports: [],
imports: [CommonModule],
exports: [],
declarations: [],
providers: [],
providers: [PresetService],
})
export class PresetModule {}
export class PresetModule { }
21 changes: 21 additions & 0 deletions src/preset/preset.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { inject, TestBed } from '@angular/core/testing';

import { PRESET_TYPES_TOKEN } from './preset-token';
import { PresetService } from './preset.service';

class MockPreset { }

describe('Service: Preset', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: PRESET_TYPES_TOKEN, useValue: MockPreset, multi: true },
PresetService,
]
});
});

it('should ...', inject([PresetService], (service: PresetService) => {
expect(service).toBeTruthy();
}));
});
48 changes: 48 additions & 0 deletions src/preset/preset.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ComponentFactoryResolver, ComponentRef, Injectable, Injector, OnDestroy } from '@angular/core';

import { PRESET_TYPES_TOKEN, PresetType } from './preset-token';

@Injectable()
export class PresetService implements OnDestroy {

private presetTypes = this.injector.get(PRESET_TYPES_TOKEN);
private presetCompRefs: ComponentRef<any>[] = [];
private finalPresetComp: any;

constructor(
private injector: Injector,
private compResolver: ComponentFactoryResolver,
) { }

getPreset<T = any>(): T {
if (this.presetTypes.length && !this.presetCompRefs.length) {
this.presetCompRefs = this.presetTypes
.map(presetType => this.createCompFromType(presetType));
}

if (!this.finalPresetComp) {
this.finalPresetComp = this.mergeCompRefs(this.presetCompRefs);
}

return this.finalPresetComp;
}

/** @internal */
ngOnDestroy() {
this.presetCompRefs
.forEach(presetCompRef => presetCompRef.destroy());
this.presetCompRefs = [];
}

private createCompFromType<T>(type: PresetType<T>) {
return this.compResolver
.resolveComponentFactory(type)
.create(this.injector);
}

private mergeCompRefs<T>(compRefs: ComponentRef<T>[]): T {
return compRefs.reduce((comp, compRef) =>
Object.assign(comp, compRef.instance), {} as T);
}

}

0 comments on commit 5503e68

Please sign in to comment.