Skip to content
This repository has been archived by the owner on Nov 6, 2024. It is now read-only.

Commit

Permalink
Change default container in MzInjectionService for document.body + se…
Browse files Browse the repository at this point in the history
…tRootViewContainer parameter to Element (#242)
  • Loading branch information
jfcere authored and scote committed Nov 20, 2017
1 parent 7887729 commit 9f40996
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 77 deletions.
4 changes: 1 addition & 3 deletions src/app/modal/services/modal.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ export class MzModalService {
/**
* Open modal component.
*
* @template T
* @param {Type<MzBaseModal>} componentClass
* @param {*} [options={}]
* @returns {ComponentRef<MzBaseModal>}
*
* @memberOf MzModalService
* @memberof MzModalService
*/
open(componentClass: Type<MzBaseModal>, options: any = {}): ComponentRef<MzBaseModal> {
const componentRef = this.injectionService.appendComponent(componentClass, options);
Expand Down
4 changes: 2 additions & 2 deletions src/app/modal/services/modal.service.view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('MzModalService:view', () => {
// expect not be in the DOM
expect(modal()).toBeNull();

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);
modalService.open(MzTestModalComponent, options);

expect(injectionService.appendComponent).toHaveBeenCalledWith(MzTestModalComponent, options);
Expand All @@ -78,7 +78,7 @@ describe('MzModalService:view', () => {
const injectionService: MzInjectionService = TestBed.get(MzInjectionService);
const modalService: MzModalService = TestBed.get(MzModalService);

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);

const componentRef = modalService.open(MzTestModalComponent);

Expand Down
72 changes: 24 additions & 48 deletions src/app/shared/injection/injection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {

@Injectable()
export class MzInjectionService {
private container: ComponentRef<any>;
private container: Element;

constructor(
private applicationRef: ApplicationRef,
Expand All @@ -24,17 +24,15 @@ export class MzInjectionService {
* @template T
* @param {Type<T>} componentClass
* @param {*} [options={}]
* @param {Element} [location=this.getRootViewContainerNode()]
* @param {Element} [location=this.getContainerElement()]
* @returns {ComponentRef<T>}
*
* @memberOf MzInjectionService
* @memberof MzInjectionService
*/
appendComponent<T>(
componentClass: Type<T>,
options: any = {},
location: Element = this.getRootViewContainerNode(),
location: Element = this.getContainerElement(),
): ComponentRef<T> {

// instantiate component to load
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
const componentRef = componentFactory.create(this.injector);
Expand All @@ -58,69 +56,47 @@ export class MzInjectionService {
}

/**
* Overrides the default root view container.
*
* @param {any} container
* Overrides the default container element.
*
* @memberOf MzInjectionService
* @param {Element} container
* @memberof MzInjectionService
*/
setRootViewContainer(container: any): void {
setRootViewContainer(container: Element): void {
this.container = container;
}

/**
* Gets the root view container to inject the component to.
*
* @template T
* @returns {ComponentRef<T>}
*
* @memberOf MzInjectionService
*/
private getRootViewContainer<T>(): ComponentRef<T> {
if (this.container) {
return this.container;
}

const rootComponents = this.applicationRef['_rootComponents'];
if (rootComponents.length) {
return rootComponents[0];
}

throw Error('View Container not found! It needs to be manually set via setRootViewContainer.');
}

/**
* Gets the html element for a component ref.
*
* @private
* @param {ComponentRef<any>} componentRef
* @returns {HTMLElement}
*
* @memberOf MzInjectionService
* @returns {Element}
* @memberof MzInjectionService
*/
private getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {
return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
private getComponentRootNode(componentRef: ComponentRef<any>): Element {
return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as Element;
}

/**
* Gets the root component container html element.
*
* @returns {HTMLElement}
* Gets the container element.
*
* @memberOf MzInjectionService
* @private
* @returns {Element}
* @memberof MzInjectionService
*/
private getRootViewContainerNode(): HTMLElement {
const rootViewContainer = this.getRootViewContainer();
return this.getComponentRootNode(rootViewContainer);
private getContainerElement(): Element {
return this.container || document.body;
}

/**
* Projects the inputs onto the component.
*
* @param {ComponentRef<any>} component
* @private
* @template T
* @param {ComponentRef<T>} component
* @param {*} options
* @returns {ComponentRef<any>}
*
* @memberOf MzInjectionService
* @returns {ComponentRef<T>}
* @memberof MzInjectionService
*/
private projectComponentInputs<T>(component: ComponentRef<T>, options: any): ComponentRef<T> {
if (options) {
Expand Down
31 changes: 7 additions & 24 deletions src/app/shared/injection/injection.service.view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('MzInjectionService:view', () => {
let nativeElement: any;

function testComponent(): HTMLElement {
return nativeElement.querySelector('mz-test');
return <HTMLElement>document.querySelector('mz-test');
}

it('should inject component in the DOM', async(() => {
Expand All @@ -51,7 +51,7 @@ describe('MzInjectionService:view', () => {
// expect not be in the DOM
expect(testComponent()).toBeNull();

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);
injectionService.appendComponent(MzTestComponent);

// expect to be in the DOM
Expand All @@ -68,7 +68,7 @@ describe('MzInjectionService:view', () => {

const injectionService: MzInjectionService = TestBed.get(MzInjectionService);

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);
const componentRef = injectionService.appendComponent(MzTestComponent, { inputProperty: 'input-property-x' });

expect(componentRef.instance.inputProperty).toBe('input-property-x');
Expand All @@ -84,7 +84,7 @@ describe('MzInjectionService:view', () => {
const applicationRef: ApplicationRef = TestBed.get(ApplicationRef);
const injectionService: MzInjectionService = TestBed.get(MzInjectionService);

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);
const componentRef = injectionService.appendComponent(MzTestComponent);

// expect to be in the DOM
Expand Down Expand Up @@ -116,34 +116,17 @@ describe('MzInjectionService:view', () => {
});
}));

it('should append component to application root component in the DOM when location not provided', async(() => {
it('should append component to document.body in the DOM when location not provided', async(() => {

buildComponent(``).then(fixture => {
nativeElement = fixture.nativeElement;
fixture.detectChanges();

const applicationRef: ApplicationRef = TestBed.get(ApplicationRef);
const injectionService: MzInjectionService = TestBed.get(MzInjectionService);

// mock _rootComponents as this does not exists in the context of TestBed
applicationRef['_rootComponents'] = [fixture.componentRef];

injectionService.appendComponent(MzTestComponent);

expect(testComponent().parentElement).toBe(fixture.nativeElement);
});
}));

it('should throw an error when applicationRef does not have _rootComponents and no default location is set', async(() => {

buildComponent(``).then(fixture => {
nativeElement = fixture.nativeElement;
fixture.detectChanges();

const injectionService: MzInjectionService = TestBed.get(MzInjectionService);

expect(() => injectionService.appendComponent(MzTestComponent))
.toThrowError('View Container not found! It needs to be manually set via setRootViewContainer.');
expect(testComponent().parentElement).toBe(document.body);
});
}));
});
Expand All @@ -163,7 +146,7 @@ describe('MzInjectionService:view', () => {

const injectionService: MzInjectionService = TestBed.get(MzInjectionService);

injectionService.setRootViewContainer(fixture.componentRef);
injectionService.setRootViewContainer(nativeElement);
injectionService.appendComponent(MzTestComponent);

expect(testComponent().parentElement).toBe(fixture.nativeElement);
Expand Down

0 comments on commit 9f40996

Please sign in to comment.