Reputation: 61724
In my Angular 4 app, let's assume that I'm inside a service.
At some point, I want to ask the user for a confirmation, currently I'm doing it with just a confirm(...)
request:
const result = confirm('Are you sure?');
What if instead I would like to show an ngx-bootstrap
modal with, let's say, two buttons "Yes" or "No" and obtain a similar result?
EDIT: in my case, I solved my issue by playing with Subjects. Here you can find my solution, in case it can be useful for someone else. However that solution does not solve this question which is about returning a value from a modal, so I leave it open.
Upvotes: 50
Views: 73949
Reputation: 119
Try this!!!! Create modal options with a yes function and a no function in the options. Receive args as @Input...
import { Component, OnInit, Input } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
@Component({
selector: 'confirm-box',
templateUrl: './confirm-box.component.html',
styleUrls: ['./confirm-box.component.css']
})
export class ConfirmBoxComponent implements OnInit {
private _args: any;
public get args(): any {
return this._args;
}
@Input()
public set args(value: any) {
this._args = value;
}
constructor(private activeModal: BsModalRef) {
}
ngOnInit(): void {
}
public no(): void {
this.args.noFunction();
this.activeModal.hide();
}
public yes(): void {
this.args.yesFunction();
this.activeModal.hide();
}
}
And then the component or service that launches the dialog:
import { BsModalService, BsModalRef, ModalOptions } from 'ngx-bootstrap/modal';
import { ConfirmBoxComponent } from '../../dialogs/confirm-box/confirm-box.component';
export class AreYouSure {
private activeModal: BsModalRef;
constructor(private modalService: BsModalService) {
//Wait five seconds before launching the confirmbox
setTimeout(()=>{
this.tryLaunchConfirm();
}, 5000);
}
private tryLaunchConfirm(): void {
const config: ModalOptions = {
initialState: {
args: {
title: "Confirm This",
message: "Are you really sure???",
yesFunction: () => { console.log("YES!!!! was clicked."); },
noFunction: () => { console.log("NO!!!! was clicked."); }
}
}
}
this.activeModal = this.modalService.show(ConfirmBoxComponent, config);
}
}
Upvotes: 1
Reputation: 11184
Try like this :
myexample it's working correctly. hope this will help you
home.module.ts
import { ModalModule } from 'ngx-bootstrap';
@NgModule({
imports: [
ModalModule.forRoot()
]
})
home.component.html
<button class="btn btn-primary" (click)="openConfirmDialog()">Open Confirm box
</button>
home.component.ts
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/modal-options.class';
export class HomeComponent {
public modalRef: BsModalRef;
constructor(
private homeService: HomeService,
private modalService: BsModalService
) { }
openConfirmDialog() {
this.modalRef = this.modalService.show(HomeModalComponent);
this.modalRef.content.onClose.subscribe(result => {
console.log('results', result);
})
}
}
home-modal.component.html
<div class="alert-box">
<div class="modal-header">
<h4 class="modal-title">Confirm</h4>
<button type="button" class="close" aria-label="Close" (click)="bsModalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure want to delete this node?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="onConfirm()">Yes</button>
<button type="button" class="btn btn-secondary" (click)="onCancel()">No</button>
</div>
</div>
home-modal.component.ts
import { Subject } from 'rxjs/Subject';
import { BsModalRef } from 'ngx-bootstrap/modal';
export class HomeModalComponent {
public onClose: Subject<boolean>;
constructor(private _bsModalRef: BsModalRef) { }
public ngOnInit(): void {
this.onClose = new Subject();
}
public onConfirm(): void {
this.onClose.next(true);
this._bsModalRef.hide();
}
public onCancel(): void {
this.onClose.next(false);
this._bsModalRef.hide();
}
}
Upvotes: 140
Reputation: 2290
I do not know if that suits you, but I used a service with Subject. In parent component it is enough to subscribe and unsubscribe, in modal component, when user clicks confirm button, then just emit value using next.
I'm sorry for not presenting a full example, but pseudocode below should present the idea.
Service:
export class SomeService{
yourSubject: new Subject<string>();
}
Parent component:
...
ngOnInit(){
this.bsModalRef = this.someService.yourSubject.subscribe ( val => ...);
}
ngOnDestroy(){
this.bsModalRef.unsubscribe();
}
...
Modal component:
...
onSaveAction(){
this.someService.yourSubject.next(val);
}
...
Ps. of course you need to provide service in proper place and inject it into components :-)
Upvotes: 1
Reputation: 336
If you are using a later version of Angular you might get an error due to the location of BsModalRef that had moved:
Use this location:
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
rather than:
import { BsModalRef } from 'ngx-bootstrap/modal/modal-options.class';
Upvotes: 1
Reputation: 931
Try this:
home.component.ts
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal';
export class HomeComponent {
public modalRef: BsModalRef;
constructor(
private modalService: BsModalService
) { }
openConfirmDialog() {
this.modalRef = this.modalService.show(HomeModalComponent);
this.modalRef.content.onClose = new Subject<boolean>();
this.modalRef.content.onClose.subscribe(result => {
console.log('results', result);
})
}
}
and
home-modal.component.ts
import { BsModalRef } from 'ngx-bootstrap/modal';
export class HomeModalComponent {
constructor(private bsModalRef: BsModalRef) {
}
public ngOnInit(): void {
}
public onConfirm(): void {
this.bsModalRef.content.onClose.next(true);
this.bsModalRef.hide();
}
public onCancel(): void {
this.bsModalRef.content.onClose.next(false);
this.bsModalRef.hide();
}
}
Upvotes: 1
Reputation: 155
Try with below option which is working for me. callbackOnModelWindowClose is the return value.
@Output() callbackOnModelWindowClose: EventEmitter<null> = new EventEmitter();
const initialState = {
isModelWindowView: true, bodyStyle: 'row', gridDataList: this.scheduleList
};
this.modalRef = this.modalService.show(YourComponent,
Object.assign({}, this.modalConfig, { class: 'modal-dialog-centered', initialState });
this.modalRef.content.callbackOnModelWindowClose.take(1).subscribe(() => {
your code here..
});
Upvotes: 0
Reputation: 785
I understand that most of the answers above are completely valid, but that the main goal is be able to invoke the confirmation dialog in this way...
async openModalConfirmation() {
const result = await this.confirmationSvc.confirm('Confirm this...');
if (result) {
console.log('Yes!');
} else {
console.log('Oh no...');
}
}
Note that this is mostly syntactic sugar to simplify the use of a promise and the asynchronous stuff.
I think it's what the OP was looking for and probably can be reworked to support returning any other data type (apart from a boolean).
The rest of the code below (not including the template to keep this short), pretty straightforward..
ModalConfirmationService
import { ModalConfirmationComponent } from './component';
@Injectable()
export class ModalConfirmationService {
constructor(private bsModalService: BsModalService) {}
confirm(message: string): Promise<boolean> {
const modal = this.bsModalService.show(ModalConfirmationComponent, { initialState: { message: message }});
return new Promise<boolean>((resolve, reject) => modal.content.result.subscribe((result) => resolve(result) ));
}
}
ModalConfirmationComponent
import { Component, Input, Output, EventEmitter} from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
import { Subject } from 'rxjs/Subject';
@Component({
templateUrl: './component.html'
})
export class ModalConfirmationComponent {
@Input() message: string;
result: Subject<boolean> = new Subject<boolean>();
constructor(public modalRef: BsModalRef) { }
confirm(): void {
this.result.next(true);
this.modalRef.hide();
}
decline(): void {
this.result.next(false);
this.modalRef.hide();
}
}
Upvotes: 5
Reputation: 2801
@ShinDarth You can add this function in your service and call this funcion whenever required.
In your Service, create this function
openConfirmDialogBox() {
this.modalRef = this.modalService.show(DemoModalComponent);
this.modalRef.content.action.take(1)
.subscribe((value) => {
console.log(value) // here value passed on clicking ok will be printed in console. Here true will be printed if OK is clicked
return value;
}, (err) => {
return false;
});
}
In your demo-modal.component.ts, create an EventEmitter
@Output() action = new EventEmitter();
public onClickOK() {
this.action.emit(true); //Can send your required data here instead of true
}
public onClickCANCEL() {
this.action.emit(false); //Can send your required data here instead of true
}
I hope this would help you
Upvotes: 4
Reputation: 31940
I used the solution from @Chandru, however to return a true
or false
, instead of:
openConfirmDialog() {
this.modalRef = this.modalService.show(HomeModalComponent);
this.modalRef.content.onClose.subscribe(result => {
console.log('results', result);
})
}
I simply used:
openConfirmDialog() {
this.modalRef = this.modalService.show(HomeModalComponent);
return this.modalRef.content.onClose;
}
Upvotes: 10