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

Adopt dynamic component service #6

Merged
merged 5 commits into from
Dec 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
"@angular/platform-browser": "^4.3.6",
"@angular/router": "^4.3.6",
"@skyux/animations": "^3.0.0-rc.0",
"@skyux/core": "^3.1.0",
"@skyux/core": "^3.5.0",
"@skyux/i18n": "^3.3.0",
"@skyux/indicators": "^3.0.0-rc.1"
},
"dependencies": {},
"devDependencies": {
"@blackbaud/skyux": "2.28.1",
"@blackbaud/skyux-builder": "1.28.0",
"@blackbaud/skyux": "2.34.0",
"@blackbaud/skyux-builder": "1.30.0",
"@skyux-sdk/builder-plugin-skyux": "1.0.0-rc.5"
}
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ import {
SkyLibResourcesService
} from '@skyux/i18n';

import {
SkyLibResourcesTestService
} from '@skyux/i18n/testing';

import {
SkyToastModule
} from '../toast.module';
Expand Down Expand Up @@ -55,10 +51,7 @@ import {
SkyToastBodyTestComponent
],
providers: [
{
provide: SkyLibResourcesService,
useClass: SkyLibResourcesTestService
}
SkyLibResourcesService
]
})
export class SkyToastFixturesModule { }
39 changes: 30 additions & 9 deletions src/app/public/modules/toast/toast-adapter.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// #region imports
import {
RendererFactory2
RendererFactory2,
ApplicationRef
} from '@angular/core';

import {
TestBed
TestBed,
inject
} from '@angular/core/testing';

import {
Expand All @@ -23,6 +25,7 @@ describe('Toast adapter service', () => {
appendCalledCount: 0,
removeCalledCount: 0
};
let applicationRef: ApplicationRef;

beforeEach(() => {
let rendererMock = {
Expand All @@ -44,13 +47,31 @@ describe('Toast adapter service', () => {
adapter = TestBed.get(SkyToastAdapterService);
});

it('should append element to body', () => {
adapter.appendToBody(undefined);
expect(rendererCallCounts.appendCalledCount).toBe(1);
});
beforeEach(
inject(
[
ApplicationRef
],
(
_applicationRef: ApplicationRef
) => {
applicationRef = _applicationRef;
}
)
);

it('should remove element from body', () => {
adapter.removeHostElement();
expect(rendererCallCounts.removeCalledCount).toBe(1);
it('should scroll to the bottom of an element correctly', () => {
spyOn(window, 'setTimeout').and.callFake((fun: Function) => {
fun();
});
let elementRefMock: any = {
nativeElement: {
scrollTop: undefined,
scrollHeight: 40
}
};
adapter.scrollBottom(elementRefMock);
applicationRef.tick();
expect(elementRefMock.nativeElement.scrollTop).toBe(40);
});
});
22 changes: 2 additions & 20 deletions src/app/public/modules/toast/toast-adapter.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// #region imports
import {
ElementRef,
Injectable,
Renderer2,
RendererFactory2
Injectable
} from '@angular/core';

import {
Expand All @@ -13,26 +11,10 @@ import {

@Injectable()
export class SkyToastAdapterService {
private hostElement: any;
private renderer: Renderer2;

constructor(
private rendererFactory: RendererFactory2,
private windowRef: SkyWindowRefService
) {
this.renderer = this.rendererFactory.createRenderer(undefined, undefined);
}

public appendToBody(element: any): void {
const body = this.windowRef.getWindow().document.body;
this.hostElement = element;
this.renderer.appendChild(body, element);
}

public removeHostElement(): void {
const document = this.windowRef.getWindow().document;
this.renderer.removeChild(document.body, this.hostElement);
}
) { }

public scrollBottom(elementRef: ElementRef): void {
const element = elementRef.nativeElement;
Expand Down
6 changes: 6 additions & 0 deletions src/app/public/modules/toast/toast.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import {
import {
SkyToastComponent
} from './toast.component';

import {
SkyToastService
} from './toast.service';
// #endregion

describe('Toast component', () => {
Expand All @@ -41,6 +45,8 @@ describe('Toast component', () => {
});

afterEach(() => {
TestBed.get(SkyToastService).ngOnDestroy();
fixture.detectChanges();
fixture.destroy();
});

Expand Down
15 changes: 12 additions & 3 deletions src/app/public/modules/toast/toast.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
import {
NgModule
} from '@angular/core';

import {
CommonModule
} from '@angular/common';

import {
SkyWindowRefService,
SkyDynamicComponentModule
} from '@skyux/core';

import {
SkyI18nModule
} from '@skyux/i18n';
import {
SkyWindowRefService
} from '@skyux/core';

import {
SkyIconModule
} from '@skyux/indicators';
Expand All @@ -23,15 +27,19 @@ import {
import {
SkyToastAdapterService
} from './toast-adapter.service';

import {
SkyToastBodyComponent
} from './toast-body.component';

import {
SkyToastComponent
} from './toast.component';

import {
SkyToasterComponent
} from './toaster.component';

import {
SkyToastService
} from './toast.service';
Expand All @@ -45,6 +53,7 @@ import {
],
imports: [
CommonModule,
SkyDynamicComponentModule,
SkyI18nModule,
SkyIconModule,
SkyToastResourcesModule
Expand Down
36 changes: 27 additions & 9 deletions src/app/public/modules/toast/toast.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
} from '@angular/core';

import {
TestBed
TestBed,
inject
} from '@angular/core/testing';

import 'rxjs/add/operator/take';
Expand All @@ -13,6 +14,10 @@ import {
expect
} from '@blackbaud/skyux-builder/runtime/testing/browser';

import {
SkyDynamicComponentService
} from '@skyux/core';

import {
SkyToastFixturesModule
} from './fixtures';
Expand All @@ -36,6 +41,7 @@ import {

describe('Toast service', () => {
let toastService: SkyToastService;
let applicationRef: ApplicationRef;

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -49,20 +55,31 @@ describe('Toast service', () => {
appendToBody() { },
removeHostElement() { }
}
},
{
provide: ApplicationRef,
useValue: {
attachView() {},
detachView() {}
}
}
]
});

toastService = TestBed.get(SkyToastService);
});

beforeEach(
inject(
[
ApplicationRef
],
(
_applicationRef: ApplicationRef
) => {
applicationRef = _applicationRef;
}
)
);

afterEach(() => {
toastService.ngOnDestroy();
applicationRef.tick();
});

it('should only create a single host component', () => {
const spy = spyOn(toastService as any, 'createHostComponent').and.callThrough();
toastService.openMessage('message');
Expand All @@ -77,7 +94,8 @@ describe('Toast service', () => {

it('should only remove the host element if it exists', () => {
toastService.openMessage('message');
const spy = spyOn(toastService['host'], 'destroy').and.callThrough();
const dynamicService = TestBed.get(SkyDynamicComponentService);
const spy = spyOn(dynamicService, 'removeComponent').and.callThrough();
toastService['removeHostComponent']();
toastService['removeHostComponent']();
expect(spy.calls.count()).toEqual(1);
Expand Down
41 changes: 13 additions & 28 deletions src/app/public/modules/toast/toast.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// #region imports
import {
ApplicationRef,
ComponentRef,
ComponentFactoryResolver,
EmbeddedViewRef,
Injectable,
Injector,
OnDestroy,
Provider
} from '@angular/core';
Expand All @@ -18,6 +14,10 @@ import {
Observable
} from 'rxjs/Observable';

import {
SkyDynamicComponentService
} from '@skyux/core';

import {
SkyToastConfig
} from './types';
Expand All @@ -26,10 +26,6 @@ import {
SkyToast
} from './toast';

import {
SkyToastAdapterService
} from './toast-adapter.service';

import {
SkyToastBodyComponent
} from './toast-body.component';
Expand Down Expand Up @@ -59,15 +55,14 @@ export class SkyToastService implements OnDestroy {
private _toastStream = new BehaviorSubject<SkyToast[]>([]);

constructor(
private appRef: ApplicationRef,
private resolver: ComponentFactoryResolver,
private injector: Injector,
private adapter: SkyToastAdapterService
private dynamicComponentService: SkyDynamicComponentService
) { }

public ngOnDestroy() {
this.closeAll();
this.removeHostComponent();
if (this.host) {
this.closeAll();
this.removeHostComponent();
}
this._toastStream.complete();
}

Expand Down Expand Up @@ -125,7 +120,7 @@ export class SkyToastService implements OnDestroy {

private addToast(toast: SkyToast): void {
if (!this.host) {
this.host = this.createHostComponent();
this.createHostComponent();
}

this.toasts.push(toast);
Expand All @@ -141,25 +136,15 @@ export class SkyToastService implements OnDestroy {
}

private createHostComponent(): ComponentRef<SkyToasterComponent> {
const componentRef = this.resolver
.resolveComponentFactory(SkyToasterComponent)
.create(this.injector);

const domElem = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0];

this.appRef.attachView(componentRef.hostView);
this.adapter.appendToBody(domElem);

return componentRef;
this.host = this.dynamicComponentService.createComponent(SkyToasterComponent);
return this.host;
}

private removeHostComponent() {
if (this.host) {
this.appRef.detachView(this.host.hostView);
this.host.destroy();
this.dynamicComponentService.removeComponent(this.host);
this.host = undefined;
}

this.adapter.removeHostElement();
}
}
Loading