Skip to content

Commit

Permalink
fix: replace ComponentFactory with new createComponent API
Browse files Browse the repository at this point in the history
Fixes #4343
  • Loading branch information
maxokorokov committed Jul 28, 2022
1 parent b251b5c commit 9a011f3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 60 deletions.
46 changes: 22 additions & 24 deletions src/modal/modal-stack.ts
@@ -1,16 +1,16 @@
/* eslint-disable deprecation/deprecation */
import {DOCUMENT} from '@angular/common';
import {
ApplicationRef,
ComponentFactoryResolver,
ComponentRef,
createComponent,
EventEmitter,
Inject,
Injectable,
Injector,
NgZone,
RendererFactory2,
TemplateRef
TemplateRef,
Type
} from '@angular/core';
import {Subject} from 'rxjs';

Expand Down Expand Up @@ -66,8 +66,7 @@ export class NgbModalStack {
}
}

open(moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, options: NgbModalOptions):
NgbModalRef {
open(contentInjector: Injector, content: any, options: NgbModalOptions): NgbModalRef {
const containerEl = options.container instanceof HTMLElement ? options.container : isDefined(options.container) ?
this._document.querySelector(options.container) :
this._document.body;
Expand All @@ -80,12 +79,11 @@ export class NgbModalStack {
this._hideScrollBar();

const activeModal = new NgbActiveModal();
const contentRef =
this._getContentRef(moduleCFR, options.injector || contentInjector, content, activeModal, options);
const contentRef = this._getContentRef(options.injector || contentInjector, content, activeModal, options);

let backdropCmptRef: ComponentRef<NgbModalBackdrop>| undefined =
options.backdrop !== false ? this._attachBackdrop(moduleCFR, containerEl) : undefined;
let windowCmptRef: ComponentRef<NgbModalWindow> = this._attachWindowComponent(moduleCFR, containerEl, contentRef);
options.backdrop !== false ? this._attachBackdrop(containerEl) : undefined;
let windowCmptRef: ComponentRef<NgbModalWindow> = this._attachWindowComponent(containerEl, contentRef.nodes);
let ngbModalRef: NgbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);

this._registerModalRef(ngbModalRef);
Expand Down Expand Up @@ -124,18 +122,18 @@ export class NgbModalStack {

hasOpenModals(): boolean { return this._modalRefs.length > 0; }

private _attachBackdrop(moduleCFR: ComponentFactoryResolver, containerEl: any): ComponentRef<NgbModalBackdrop> {
let backdropFactory = moduleCFR.resolveComponentFactory(NgbModalBackdrop);
let backdropCmptRef = backdropFactory.create(this._injector);
private _attachBackdrop(containerEl: Element): ComponentRef<NgbModalBackdrop> {
let backdropCmptRef = createComponent(
NgbModalBackdrop, {environmentInjector: this._applicationRef.injector, elementInjector: this._injector});
this._applicationRef.attachView(backdropCmptRef.hostView);
containerEl.appendChild(backdropCmptRef.location.nativeElement);
return backdropCmptRef;
}

private _attachWindowComponent(moduleCFR: ComponentFactoryResolver, containerEl: any, contentRef: any):
ComponentRef<NgbModalWindow> {
let windowFactory = moduleCFR.resolveComponentFactory(NgbModalWindow);
let windowCmptRef = windowFactory.create(this._injector, contentRef.nodes);
private _attachWindowComponent(containerEl: Element, projectableNodes: Node[][]): ComponentRef<NgbModalWindow> {
let windowCmptRef = createComponent(
NgbModalWindow,
{environmentInjector: this._applicationRef.injector, elementInjector: this._injector, projectableNodes});
this._applicationRef.attachView(windowCmptRef.hostView);
containerEl.appendChild(windowCmptRef.location.nativeElement);
return windowCmptRef;
Expand All @@ -158,7 +156,7 @@ export class NgbModalStack {
}

private _getContentRef(
moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, activeModal: NgbActiveModal,
contentInjector: Injector, content: Type<any>| TemplateRef<any>| string, activeModal: NgbActiveModal,
options: NgbModalOptions): ContentRef {
if (!content) {
return new ContentRef([]);
Expand All @@ -167,17 +165,17 @@ export class NgbModalStack {
} else if (isString(content)) {
return this._createFromString(content);
} else {
return this._createFromComponent(moduleCFR, contentInjector, content, activeModal, options);
return this._createFromComponent(contentInjector, content, activeModal, options);
}
}

private _createFromTemplateRef(content: TemplateRef<any>, activeModal: NgbActiveModal): ContentRef {
private _createFromTemplateRef(templateRef: TemplateRef<any>, activeModal: NgbActiveModal): ContentRef {
const context = {
$implicit: activeModal,
close(result) { activeModal.close(result); },
dismiss(reason) { activeModal.dismiss(reason); }
};
const viewRef = content.createEmbeddedView(context);
const viewRef = templateRef.createEmbeddedView(context);
this._applicationRef.attachView(viewRef);
return new ContentRef([viewRef.rootNodes], viewRef);
}
Expand All @@ -188,12 +186,12 @@ export class NgbModalStack {
}

private _createFromComponent(
moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, context: NgbActiveModal,
contentInjector: Injector, componentType: Type<any>, context: NgbActiveModal,
options: NgbModalOptions): ContentRef {
const contentCmptFactory = moduleCFR.resolveComponentFactory(content);
const modalContentInjector =
const elementInjector =
Injector.create({providers: [{provide: NgbActiveModal, useValue: context}], parent: contentInjector});
const componentRef = contentCmptFactory.create(modalContentInjector);
const componentRef =
createComponent(componentType, {environmentInjector: this._applicationRef.injector, elementInjector});
const componentNativeEl = componentRef.location.nativeElement;
if (options.scrollable) {
(componentNativeEl as HTMLElement).classList.add('component-host-scrollable');
Expand Down
9 changes: 3 additions & 6 deletions src/modal/modal.ts
@@ -1,5 +1,4 @@
/* eslint-disable deprecation/deprecation */
import {Injectable, Injector, ComponentFactoryResolver} from '@angular/core';
import {Injectable, Injector} from '@angular/core';

import {NgbModalOptions, NgbModalConfig} from './modal-config';
import {NgbModalRef} from './modal-ref';
Expand All @@ -13,9 +12,7 @@ import {NgbModalStack} from './modal-stack';
*/
@Injectable({providedIn: 'root'})
export class NgbModal {
constructor(
private _moduleCFR: ComponentFactoryResolver, private _injector: Injector, private _modalStack: NgbModalStack,
private _config: NgbModalConfig) {}
constructor(private _injector: Injector, private _modalStack: NgbModalStack, private _config: NgbModalConfig) {}

/**
* Opens a new modal window with the specified content and supplied options.
Expand All @@ -28,7 +25,7 @@ export class NgbModal {
*/
open(content: any, options: NgbModalOptions = {}): NgbModalRef {
const combinedOptions = {...this._config, animation: this._config.animation, ...options};
return this._modalStack.open(this._moduleCFR, this._injector, content, combinedOptions);
return this._modalStack.open(this._injector, content, combinedOptions);
}

/**
Expand Down
48 changes: 23 additions & 25 deletions src/offcanvas/offcanvas-stack.ts
@@ -1,15 +1,15 @@
/* eslint-disable deprecation/deprecation */
import {DOCUMENT} from '@angular/common';
import {
ApplicationRef,
ComponentFactoryResolver,
ComponentRef,
createComponent,
EventEmitter,
Inject,
Injectable,
Injector,
NgZone,
TemplateRef
TemplateRef,
Type
} from '@angular/core';
import {finalize} from 'rxjs/operators';
import {Subject} from 'rxjs';
Expand Down Expand Up @@ -58,8 +58,7 @@ export class NgbOffcanvasStack {
}
}

open(moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any, options: NgbOffcanvasOptions):
NgbOffcanvasRef {
open(contentInjector: Injector, content: any, options: NgbOffcanvasOptions): NgbOffcanvasRef {
const containerEl = options.container instanceof HTMLElement ? options.container : isDefined(options.container) ?
this._document.querySelector(options.container) :
this._document.body;
Expand All @@ -72,11 +71,11 @@ export class NgbOffcanvasStack {
}

const activeOffcanvas = new NgbActiveOffcanvas();
const contentRef = this._getContentRef(moduleCFR, options.injector || contentInjector, content, activeOffcanvas);
const contentRef = this._getContentRef(options.injector || contentInjector, content, activeOffcanvas);

let backdropCmptRef: ComponentRef<NgbOffcanvasBackdrop>| undefined =
options.backdrop !== false ? this._attachBackdrop(moduleCFR, containerEl) : undefined;
let panelCmptRef: ComponentRef<NgbOffcanvasPanel> = this._attachWindowComponent(moduleCFR, containerEl, contentRef);
options.backdrop !== false ? this._attachBackdrop(containerEl) : undefined;
let panelCmptRef: ComponentRef<NgbOffcanvasPanel> = this._attachWindowComponent(containerEl, contentRef.nodes);
let ngbOffcanvasRef: NgbOffcanvasRef =
new NgbOffcanvasRef(panelCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);

Expand All @@ -102,18 +101,18 @@ export class NgbOffcanvasStack {

hasOpenOffcanvas(): boolean { return !!this._offcanvasRef; }

private _attachBackdrop(moduleCFR: ComponentFactoryResolver, containerEl: any): ComponentRef<NgbOffcanvasBackdrop> {
let backdropFactory = moduleCFR.resolveComponentFactory(NgbOffcanvasBackdrop);
let backdropCmptRef = backdropFactory.create(this._injector);
private _attachBackdrop(containerEl: Element): ComponentRef<NgbOffcanvasBackdrop> {
let backdropCmptRef = createComponent(
NgbOffcanvasBackdrop, {environmentInjector: this._applicationRef.injector, elementInjector: this._injector});
this._applicationRef.attachView(backdropCmptRef.hostView);
containerEl.appendChild(backdropCmptRef.location.nativeElement);
return backdropCmptRef;
}

private _attachWindowComponent(moduleCFR: ComponentFactoryResolver, containerEl: any, contentRef: any):
ComponentRef<NgbOffcanvasPanel> {
let panelFactory = moduleCFR.resolveComponentFactory(NgbOffcanvasPanel);
let panelCmptRef = panelFactory.create(this._injector, contentRef.nodes);
private _attachWindowComponent(containerEl: Element, projectableNodes: Node[][]): ComponentRef<NgbOffcanvasPanel> {
let panelCmptRef = createComponent(
NgbOffcanvasPanel,
{environmentInjector: this._applicationRef.injector, elementInjector: this._injector, projectableNodes});
this._applicationRef.attachView(panelCmptRef.hostView);
containerEl.appendChild(panelCmptRef.location.nativeElement);
return panelCmptRef;
Expand All @@ -136,7 +135,7 @@ export class NgbOffcanvasStack {
}

private _getContentRef(
moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any,
contentInjector: Injector, content: Type<any>| TemplateRef<any>| string,
activeOffcanvas: NgbActiveOffcanvas): ContentRef {
if (!content) {
return new ContentRef([]);
Expand All @@ -145,17 +144,17 @@ export class NgbOffcanvasStack {
} else if (isString(content)) {
return this._createFromString(content);
} else {
return this._createFromComponent(moduleCFR, contentInjector, content, activeOffcanvas);
return this._createFromComponent(contentInjector, content, activeOffcanvas);
}
}

private _createFromTemplateRef(content: TemplateRef<any>, activeOffcanvas: NgbActiveOffcanvas): ContentRef {
private _createFromTemplateRef(templateRef: TemplateRef<any>, activeOffcanvas: NgbActiveOffcanvas): ContentRef {
const context = {
$implicit: activeOffcanvas,
close(result) { activeOffcanvas.close(result); },
dismiss(reason) { activeOffcanvas.dismiss(reason); }
};
const viewRef = content.createEmbeddedView(context);
const viewRef = templateRef.createEmbeddedView(context);
this._applicationRef.attachView(viewRef);
return new ContentRef([viewRef.rootNodes], viewRef);
}
Expand All @@ -165,13 +164,12 @@ export class NgbOffcanvasStack {
return new ContentRef([[component]]);
}

private _createFromComponent(
moduleCFR: ComponentFactoryResolver, contentInjector: Injector, content: any,
context: NgbActiveOffcanvas): ContentRef {
const contentCmptFactory = moduleCFR.resolveComponentFactory(content);
const offcanvasContentInjector =
private _createFromComponent(contentInjector: Injector, componentType: Type<any>, context: NgbActiveOffcanvas):
ContentRef {
const elementInjector =
Injector.create({providers: [{provide: NgbActiveOffcanvas, useValue: context}], parent: contentInjector});
const componentRef = contentCmptFactory.create(offcanvasContentInjector);
const componentRef =
createComponent(componentType, {environmentInjector: this._applicationRef.injector, elementInjector});
const componentNativeEl = componentRef.location.nativeElement;
this._applicationRef.attachView(componentRef.hostView);
return new ContentRef([[componentNativeEl]], componentRef.hostView, componentRef);
Expand Down
8 changes: 3 additions & 5 deletions src/offcanvas/offcanvas.ts
@@ -1,5 +1,4 @@
/* eslint-disable deprecation/deprecation */
import {ComponentFactoryResolver, Injectable, Injector} from '@angular/core';
import {Injectable, Injector} from '@angular/core';
import {NgbOffcanvasConfig, NgbOffcanvasOptions} from './offcanvas-config';
import {NgbOffcanvasRef} from './offcanvas-ref';
import {NgbOffcanvasStack} from './offcanvas-stack';
Expand All @@ -15,8 +14,7 @@ import {NgbOffcanvasStack} from './offcanvas-stack';
@Injectable({providedIn: 'root'})
export class NgbOffcanvas {
constructor(
private _moduleCFR: ComponentFactoryResolver, private _injector: Injector,
private _offcanvasStack: NgbOffcanvasStack, private _config: NgbOffcanvasConfig) {}
private _injector: Injector, private _offcanvasStack: NgbOffcanvasStack, private _config: NgbOffcanvasConfig) {}

/**
* Opens a new offcanvas panel with the specified content and supplied options.
Expand All @@ -30,7 +28,7 @@ export class NgbOffcanvas {
*/
open(content: any, options: NgbOffcanvasOptions = {}): NgbOffcanvasRef {
const combinedOptions = {...this._config, animation: this._config.animation, ...options};
return this._offcanvasStack.open(this._moduleCFR, this._injector, content, combinedOptions);
return this._offcanvasStack.open(this._injector, content, combinedOptions);
}

/**
Expand Down

0 comments on commit 9a011f3

Please sign in to comment.