Skip to content

Commit

Permalink
fix(popover): fix template context not being passed, update cdk to 7.…
Browse files Browse the repository at this point in the history
…2.1 (#1153)

Closes #1084 
Closes #848
  • Loading branch information
nnixaa committed Jan 15, 2019
1 parent cb1c21e commit c83188c
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 378 deletions.
389 changes: 190 additions & 199 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"@angular-devkit/build-angular": "0.10.2",
"@angular-devkit/core": "7.0.2",
"@angular-devkit/schematics": "7.0.2",
"@angular/cdk": "7.0.0",
"@angular/cdk": "7.2.1",
"@angular/cli": "7.0.2",
"@angular/compiler-cli": "7.0.0",
"@angular/language-service": "7.0.0",
Expand Down Expand Up @@ -174,4 +174,4 @@
"uglifyjs-webpack-plugin": "1.1.5"
},
"schematics": "./schematics/dist/collection.json"
}
}
1 change: 0 additions & 1 deletion scripts/gulp/tasks/bundle/rollup-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const ROLLUP_GLOBALS = {
'@angular/cdk/platform': 'ng.cdk.platform',
'@angular/cdk/portal': 'ng.cdk.portal',
'@angular/cdk/a11y': 'ng.cdk.a11y',
'@angular/cdk/bidi': 'ng.cdk.bidi',
'@angular/cdk/scrolling': 'ng.cdk.scrolling',


Expand Down
156 changes: 0 additions & 156 deletions src/framework/theme/components/cdk/overlay/mapping.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import {
ApplicationRef,
ComponentFactoryResolver,
ComponentRef,
Directive,
EmbeddedViewRef,
Inject,
Injectable,
Injector,
ModuleWithProviders,
NgModule,
NgZone,
TemplateRef,
ViewContainerRef,
} from '@angular/core';
import {
CdkPortal,
CdkPortalOutlet,
ComponentPortal,
DomPortalOutlet,
Portal,
PortalInjector,
PortalModule,
Expand All @@ -32,7 +24,6 @@ import {
Overlay,
OverlayConfig,
OverlayContainer,
OverlayKeyboardDispatcher,
OverlayModule,
OverlayPositionBuilder,
OverlayRef,
Expand All @@ -41,9 +32,6 @@ import {
ScrollStrategyOptions,
} from '@angular/cdk/overlay';
import { Platform } from '@angular/cdk/platform';
import { Directionality } from '@angular/cdk/bidi';

import { NB_DOCUMENT } from '../../../theme.options';


@Directive({ selector: '[nbPortal]' })
Expand All @@ -55,154 +43,10 @@ export class NbPortalOutletDirective extends CdkPortalOutlet {
}

export class NbComponentPortal<T = any> extends ComponentPortal<T> {
constructor(component: ComponentType<T>,
vcr?: ViewContainerRef,
injector?: Injector,
public cfr?: ComponentFactoryResolver) {
super(component, vcr, injector);
}
}

/**
* TODO remove after @angular/cdk@7.0.0 relased
* */
export class NbDomPortalOutlet extends DomPortalOutlet {
constructor(
/** Element into which the content is projected. */
public outletElement: Element,
private componentFactoryResolver: ComponentFactoryResolver,
private appRef: ApplicationRef,
private defaultInjector: Injector) {
super(outletElement, componentFactoryResolver, appRef, defaultInjector);
}

/**
* Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver.
* @param portal Portal to be attached
* @returns Reference to the created component.
*/
attachComponentPortal<T>(portal: NbComponentPortal<T>): ComponentRef<T> {
const resolver = portal.cfr || this.componentFactoryResolver;
const componentFactory = resolver.resolveComponentFactory(portal.component);
let componentRef: ComponentRef<T>;

// If the portal specifies a ViewContainerRef, we will use that as the attachment point
// for the component (in terms of Angular's component tree, not rendering).
// When the ViewContainerRef is missing, we use the factory to create the component directly
// and then manually attach the view to the application.
if (portal.viewContainerRef) {
componentRef = portal.viewContainerRef.createComponent(
componentFactory,
portal.viewContainerRef.length,
portal.injector || portal.viewContainerRef.parentInjector);

this.setDisposeFn(() => componentRef.destroy());
} else {
componentRef = componentFactory.create(portal.injector || this.defaultInjector);
this.appRef.attachView(componentRef.hostView);
this.setDisposeFn(() => {
this.appRef.detachView(componentRef.hostView);
componentRef.destroy();
});
}
// At this point the component has been instantiated, so we move it to the location in the DOM
// where we want it to be rendered.
this.outletElement.appendChild(this.getComponentRootNode(componentRef));

return componentRef;
}

/** Gets the root HTMLElement for an instantiated component. */
private getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {
return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
}
}

@Injectable()
export class NbOverlay extends Overlay {
protected appRef: ApplicationRef;
protected static nextUniqueId = 0;

constructor(
/** Scrolling strategies that can be used when creating an overlay. */
public scrollStrategies: ScrollStrategyOptions,
protected overlayContainer: OverlayContainer,
protected componentFactoryResolver: ComponentFactoryResolver,
protected positionBuilder: OverlayPositionBuilder,
protected keyboardDispatcher: OverlayKeyboardDispatcher,
protected injector: Injector,
protected ngZone: NgZone,
@Inject(NB_DOCUMENT) private document: any,
private directionality: Directionality) {
super(
scrollStrategies,
overlayContainer,
componentFactoryResolver,
positionBuilder,
keyboardDispatcher,
injector,
ngZone,
document,
directionality,
);
}

/**
* Creates an overlay.
* @param config Configuration applied to the overlay.
* @returns Reference to the created overlay.
*/
create(config?: OverlayConfig): OverlayRef {
const host = this.createHostElement();
const pane = this.createPaneElement(host);
const portalOutlet = this.createPortalOutlet(pane);
const overlayConfig = new OverlayConfig(config);

overlayConfig.direction = overlayConfig.direction || this.directionality.value;

return new OverlayRef(portalOutlet, host, pane, overlayConfig, this.ngZone,
this.keyboardDispatcher, this.document);
}

/**
* Creates the DOM element for an overlay and appends it to the overlay container.
* @returns Newly-created pane element
*/
protected createPaneElement(host: HTMLElement): HTMLElement {
const pane = this.document.createElement('div');

pane.id = `cdk-overlay-${NbOverlay.nextUniqueId++}`;
pane.classList.add('cdk-overlay-pane');
host.appendChild(pane);

return pane;
}

/**
* Creates the host element that wraps around an overlay
* and can be used for advanced positioning.
* @returns Newly-create host element.
*/
protected createHostElement(): HTMLElement {
const host = this.document.createElement('div');
this.overlayContainer.getContainerElement().appendChild(host);
return host;
}

/**
* Create a DomPortalOutlet into which the overlay content can be loaded.
* @param pane The DOM element to turn into a portal outlet.
* @returns A portal outlet for the given DOM element.
*/
protected createPortalOutlet(pane: HTMLElement): NbDomPortalOutlet {
// We have to resolve the ApplicationRef later in order to allow people
// to use overlay-based providers during app initialization.
if (!this.appRef) {
this.appRef = this.injector.get<ApplicationRef>(ApplicationRef);
}

return new NbDomPortalOutlet(pane, this.componentFactoryResolver, this.appRef, this.injector);
}
}

@Injectable()
Expand Down
17 changes: 10 additions & 7 deletions src/framework/theme/components/cdk/overlay/overlay-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import {
HostBinding,
Injector,
Input,
ViewChild,
ViewContainerRef,
} from '@angular/core';

import { NbPosition } from './overlay-position';
import { NbComponentPortal, NbPortalInjector, NbTemplatePortal } from './mapping';
import { NbComponentPortal, NbPortalInjector, NbPortalOutletDirective, NbTemplatePortal } from './mapping';

export abstract class NbPositionedContainer {
@Input() position: NbPosition;
Expand Down Expand Up @@ -43,10 +44,13 @@ export abstract class NbPositionedContainer {
selector: 'nb-overlay-container',
template: `
<div *ngIf="isStringContent" class="primitive-overlay">{{ content }}</div>
<ng-template nbPortalOutlet></ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NbOverlayContainerComponent {
@ViewChild(NbPortalOutletDirective) portalOutlet: NbPortalOutletDirective;

isAttached: boolean = false;

content: string;
Expand All @@ -61,17 +65,16 @@ export class NbOverlayContainerComponent {
}

attachComponentPortal<T>(portal: NbComponentPortal<T>): ComponentRef<T> {
const factory = portal.cfr.resolveComponentFactory(portal.component);
const injector = this.createChildInjector(portal.cfr);
const componentRef = this.vcr.createComponent(factory, null, injector);
portal.injector = this.createChildInjector(portal.componentFactoryResolver);
const componentRef = this.portalOutlet.attachComponentPortal(portal);
this.isAttached = true;
return componentRef;
}

attachTemplatePortal<C>(portal: NbTemplatePortal<C>): EmbeddedViewRef<C> {
const embeddedView = this.vcr.createEmbeddedView(portal.templateRef, portal.context);
this.isAttached = true;
return embeddedView;
const templateRef = this.portalOutlet.attachTemplatePortal(portal);
templateRef.detectChanges();
return templateRef;
}

attachStringContent(content: string) {
Expand Down
22 changes: 13 additions & 9 deletions src/framework/theme/components/dialog/dialog.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, NgModule } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { fakeAsync, TestBed, tick } from '@angular/core/testing';

import { NbOverlayContainerAdapter, NbOverlayService, NbViewportRulerAdapter } from '../cdk';
import { NbDialogService } from './dialog.service';
Expand Down Expand Up @@ -126,28 +126,32 @@ describe('dialog-service', () => {
expect(spy).toHaveBeenCalledTimes(0);
});

it('should close on backdrop click if closeOnBackdropClick is true', () => {
it('should close on backdrop click if closeOnBackdropClick is true', fakeAsync(() => {
dialog.open(NbTestDialogComponent, { closeOnBackdropClick: true, autoFocus: false });
queryBackdrop().dispatchEvent(new Event('click'));
tick(500);
expect(queryBackdrop()).toBeFalsy();
});
}));

it('should not close on backdrop click if closeOnBackdropClick is false', () => {
it('should not close on backdrop click if closeOnBackdropClick is false', fakeAsync(() => {
dialog.open(NbTestDialogComponent, { closeOnBackdropClick: false });
queryBackdrop().dispatchEvent(new Event('click'));
tick(500);
expect(queryBackdrop()).toBeTruthy();
});
}));

it('should close on escape press if closeOnEsc is true', () => {
it('should close on escape press if closeOnEsc is true', fakeAsync(() => {
dialog.open(NbTestDialogComponent, { closeOnEsc: true });
document.dispatchEvent(new KeyboardEvent('keyup', <any> { keyCode: 27 }));
tick(500);
expect(queryBackdrop()).toBeFalsy();
});
}));

it('should not close on escape press if closeOnEsc is false', () => {
it('should not close on escape press if closeOnEsc is false', fakeAsync(() => {
dialog.open(NbTestDialogComponent, { closeOnEsc: false });
document.dispatchEvent(new KeyboardEvent('keyup', <any> { keyCode: 27 }));
tick(500);
expect(queryBackdrop()).toBeTruthy();
});
}));
});

3 changes: 2 additions & 1 deletion src/framework/theme/components/popover/popover.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export class NbPopoverComponent extends NbPositionedContainer implements AfterVi
}

protected attachTemplate() {
this.overlayContainer.attachTemplatePortal(new NbTemplatePortal(this.content, null, this.context));
this.overlayContainer
.attachTemplatePortal(new NbTemplatePortal(this.content, null, <any>{ $implicit: this.context }));
}

protected attachComponent() {
Expand Down
2 changes: 1 addition & 1 deletion src/framework/theme/components/popover/popover.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ describe('Directive: NbPopoverDirective', () => {
expect(primitiveOverlay.textContent).toContain('test');
});

xit('should provide context', () => {
it('should provide context', () => {
fixture.componentInstance.popover.show();
fixture.detectChanges();

Expand Down
4 changes: 2 additions & 2 deletions src/framework/theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
"@angular/common": "^7.0.0",
"@angular/core": "^7.0.0",
"@angular/router": "^7.0.0",
"@angular/cdk": "^7.0.0",
"@angular/cdk": "^7.2.1",
"rxjs": "^6.3.0",
"nebular-icons": "^1.1.0"
},
"dependencies": {
"intersection-observer": "0.5.0"
},
"schematics": "./schematics/collection.json"
}
}

0 comments on commit c83188c

Please sign in to comment.