This plunker should open up a modal when the button is pressed. I have extended the existing ngx-modal but it throws error: Cannot read property 'nativeElement' of undefined.
Having looked at the console this is because "modalRoot" should be programatically assigned as a ViewChild handler for the modal. It doesn't seem to get defined when extended even though I've added the super() to my constructor, any ideas?
//our root app component
import {Component, NgModule, HostListener, ElementRef} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {ModalModule} from "ngx-modal";
import { Modal } from "ngx-modal";
@Component({
selector: 'ext-ngx-modal',
template: `<ng-content></ng-content>`,
})
export class NgxModalComponent extends Modal {
constructor() {
super();
}
openExt():void {
this.open();
}
@HostListener('document:keydown', ['$event'])
onkeydown(ev: KeyboardEvent) {
console.log("this.isOpened: " + this.isOpened;
}
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}} I am </h2>
<div class="row container-fluid">
<button (click)="myExtNgxModal.openExt()"> open my modal</button>
<ext-ngx-modal #myExtNgxModal>
<modal>
<modal-header>
<h1>Modal header</h1>
</modal-header>
<modal-content>
Press F12 see the console...press a key while modal open
</modal-content>
<modal-footer>
<button class="btn btn-primary" (click)="myModal.close()">close</button>
</modal-footer>
</modal>
</ext-ngx-modal>
</div>
</div>
`,
})
export class App {
name:string;
constructor() {
this.name = 'Angular2'
}
}
@NgModule({
imports: [ BrowserModule, ModalModule ],
declarations: [ App, NgxModalComponent ],
exports: [ NgxModalComponent ],
bootstrap: [ App ]
})
export class AppModule {}
When your NgxModalComponent
component extends the Modal
component, it will inherit the code like you would imaging.
The problem is that you are overriding it's template with your own. This is a problem since some of the code you have inherited relies on the template of the original Modal
component.
Here is an example from the source code where the Modal
is gaining access to an element in the template:
/***** FROM NGX-MODAL SOURCE *****/
@ViewChild("modalRoot")
public modalRoot: ElementRef;
When it invokes open()
, it's using this reference internally to set focus
on its native element:
/***** FROM NGX-MODAL SOURCE *****/
window.setTimeout(() => this.modalRoot.nativeElement.focus(), 0);
Since you don't have a the same template
and no element named modalRoot, it will fail.
Using ContentChild
(docs)
One solution is to use ContentChild
to get a reference to the Modal
that is wrapped inside you template. yurzui posted a plunker showing this in this comment (yurzui created this plunker, no credit to me for that!).
What he is doing is getting the modal reference and calling the open()
method on the embedded Modal
instance instead.
@ContentChild(Modal) modal: Modal;
openExt():void {
this.modal.open();
}
Rethinking your approach
Another option is to rethink if your approach of extending this modal is really needed and the correct way forward. But that is up to you :)
I hope this helps!