One possible solution of many others is to do it with the npm package @costlydeveloper/ngx-awesome-popup.
Which provides 2-way data binding between two components without breaking the object reference, the parent component (from where you call popup dialog) and child component (the one evoked inside the dialog). The child component can receive the data from the parent component and send a response payload object back.
In app.module.ts you can enable just the dialog module without importing other package features.
Import dialog module it in your AppModule
:
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent} from './app.component';
// Import your library
import {DialogConfigModule, NgxAwesomePopupModule} from '@costlydeveloper/ngx-awesome-popup';
@NgModule({
declarations: [
AppComponent
],
imports : [
BrowserModule,
// Enable package and dialog modules
NgxAwesomePopupModule.forRoot(),
DialogConfigModule.forRoot()
//
],
providers : [],
bootstrap : [AppComponent]
})
export class AppModule {
}
Setup of the ParentComponent
import {Component, OnInit} from '@angular/core';
import {ChildComponent} from './child.component';
// import library classes
import {DialogLayoutDisplay, DialogInitializer, ButtonLayoutDisplay, ButtonMaker} from '@costlydeveloper/ngx-awesome-popup';
@Component({
selector : 'app-root',
templateUrl: './app.component.html',
styleUrls : ['./app.component.scss']
})
export class ParentComponent implements OnInit {
ngOnInit() {
// Call the dialog.
this.dialog();
}
// Create the method.
dialog() {
// Instance of DialogInitializer includes any valid angular component as an argument.
const dialogPopup = new DialogInitializer(ChildComponent);
// Any data can be sent to ChildComponent.
dialogPopup.setCustomData({name: 'John', surname: 'Doe', id: 1});
// Set some configuration.
dialogPopup.setConfig({
Width : '500px',
LayoutType: DialogLayoutDisplay.NONE // SUCCESS | INFO | NONE | DANGER | WARNING
});
// Set some custom buttons as list.
// SUCCESS | INFO | NONE | DANGER | WARNING | PRIMARY | SECONDARY | LINK | DARK | LIGHT
dialogPopup.setButtons([
new ButtonMaker('Edit', 'edit', ButtonLayoutDisplay.WARNING),
new ButtonMaker('Submit', 'submit', ButtonLayoutDisplay.SUCCESS),
new ButtonMaker('Cancel', 'cancel', ButtonLayoutDisplay.SECONDARY)
]);
// Simply open the popup and listen which button is clicked and,
// receive optional payload from the ChildComponent.
const subscription = dialogPopup.openDialog$().subscribe(resp => {
// This is the response from the ChildComponent it will include
your payload data and info about which button is clicked.
// your payload data from the child component is here.
console.log('payload response: ', resp.Payload);
if (resp.ClickedButtonID === 'submit') {
// do some logic
}
subscription.unsubscribe();
});
}
}
Setup of the ChildComponent
in a way to inject the DialogBelonging dependency in the Child component constructor, which will give you options to manipulate data and trigger the various events such as button click listener and closing loader.
To send data back to ParentComponent just put your object as an argument to the close method like this: close(someObject)
, also you can implement simple logic to listen to which button is clicked and send different data. Your 2-way bound data sent from the ParentComponent is there this.dialogBelonging.CustomData
import {Component, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from 'rxjs';
import {DialogBelonging} from '@costlydeveloper/ngx-awesome-popup';
@Component({
selector: 'app-any-angular-component',
templateUrl: './any-angular.component.html',
styleUrls: ['./any-angular.component.scss']
})
export class AnyAngularComponent implements OnInit, OnDestroy{
subscriptions: Subscription[] = [];
// Dependency Injection of the dialogBelonging in the constructor is crucial.
constructor(private dialogBelonging: DialogBelonging) {}
ngOnInit(): void {
// Here is your 2 way data binded object with the Parent component.
console.log(this.dialogBelonging.CustomData);
// Subscribe to button listeners.
this.subscriptions.push(
// IDialogEventsController
this.dialogBelonging.EventsController.onButtonClick$.subscribe((_Button) => {
if (_Button.ID === 'edit') {
// Do some logic for example edit user.
} else if (_Button.ID === 'submit') {
// Do some logic and close popup.
this.dialogBelonging.EventsController.close();
}
else if (_Button.ID === 'cancel') {
// Do some logic and close popup.
this.dialogBelonging.EventsController.close();
}
})
);
}
ngOnDestroy(): void {
// Care about memory and close all subscriptions.
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}
Notice: For Angular 8:
The packahe works with angular 9+ but because of the entry component rule which is deprecated from angular 9+, you will not be able to open the ChildComponent unless you add it to the entry component list in app.module.ts
entryComponents: [Childcomponent]