Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(popover): fix template context not being passed, update cdk to 7.2.1 #1153

Merged
merged 3 commits into from
Jan 15, 2019
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
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';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, also, remove this module from rollup-config.ts


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"
}
}