Ngx-bootstrap: BsModalService confirmation modal with yes and no buttons

Created on 18 Aug 2017  路  15Comments  路  Source: valor-software/ngx-bootstrap

Greetings,
I am using BsModalService with component. i have a modal with two buttons yes and no.

I would like to know how to track which button clicked. here yes or no button. I have gone through demo, but i could not find any solution.

let bsModalRef = this.modalService.show(ConfirmDeleteComponent, { animated: true, keyboard: true, backdrop: true, ignoreBackdropClick: false });

My modal 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">&times;</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)="bsModalRef.hide()">Yes</button>
        <button type="button" class="btn btn-secondary" (click)="bsModalRef.hide()">No</button>        
    </div>
</div>
comp(docs) comp(modal)

Most helpful comment

A possible solution could be:

confirmation-modal.component.html

<form (ngSubmit)="onConfirm()" *ngIf="active">
    <div class="modal-header">
        <h4 class="modal-title pull-left">
            {{title}}
        </h4>
        <button type="button" class="close pull-right" (click)="hideConfirmationModal()" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <p>{{body}}</p>
    </div>
    <div class="modal-footer">
        <div class="text-right">
            <button type="submit" class="btn btn-success">
                Yes
            </button>
            <button type="button" class="btn btn-default" (click)="onCancel()">
                No
            </button>
        </div>
    </div>
</form>

confirmation-modal.component.ts:

import { BsModalRef } from 'ngx-bootstrap/modal';
import { Component, OnInit } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Component({
    selector: 'app-confirmation-modal',
    templateUrl: './confirmation-modal.component.html'
})
export class ConfirmationModalComponent implements OnInit {
    public active: boolean = false;
    public body: string;
    public title: string;
    public onClose: Subject<boolean>;

    public constructor(
        private _bsModalRef: BsModalRef
    ) { }

    public ngOnInit(): void {
        this.onClose = new Subject();
    }

    public showConfirmationModal(title: string, body: string): void {
        this.title = title;
        this.body =  body;
        this.active = true;
    }

    public onConfirm(): void {
        this.active = false;
        this.onClose.next(true);
        this._bsModalRef.hide();
    }

    public onCancel(): void {
        this.active = false;
        this.onClose.next(false);
        this._bsModalRef.hide();
    }

    public hideConfirmationModal(): void {
        this.active = false;
        this.onClose.next(null);
        this._bsModalRef.hide();
    }
}

opening the modal with the modal service from another component:

public showConfirmationModal(): void {
    const modal = this._bsModalService.show(ConfirmationModalComponent);
    (<ConfirmationModalComponent>modal.content).showConfirmationModal(
        'Title of modal',
        'Body text'
    );

    (<ConfirmationModalComponent>modal.content).onClose.subscribe(result => {
        if (result === true) {
            // when pressed Yes
        } else if(result === false) {
            // when pressed No
        } else {
            // When closing the modal without no or yes
        }
    });
}

All 15 comments

Hi,

I am also waiting for a solution on this. Hope to get it soon.

A possible solution could be:

confirmation-modal.component.html

<form (ngSubmit)="onConfirm()" *ngIf="active">
    <div class="modal-header">
        <h4 class="modal-title pull-left">
            {{title}}
        </h4>
        <button type="button" class="close pull-right" (click)="hideConfirmationModal()" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <p>{{body}}</p>
    </div>
    <div class="modal-footer">
        <div class="text-right">
            <button type="submit" class="btn btn-success">
                Yes
            </button>
            <button type="button" class="btn btn-default" (click)="onCancel()">
                No
            </button>
        </div>
    </div>
</form>

confirmation-modal.component.ts:

import { BsModalRef } from 'ngx-bootstrap/modal';
import { Component, OnInit } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Component({
    selector: 'app-confirmation-modal',
    templateUrl: './confirmation-modal.component.html'
})
export class ConfirmationModalComponent implements OnInit {
    public active: boolean = false;
    public body: string;
    public title: string;
    public onClose: Subject<boolean>;

    public constructor(
        private _bsModalRef: BsModalRef
    ) { }

    public ngOnInit(): void {
        this.onClose = new Subject();
    }

    public showConfirmationModal(title: string, body: string): void {
        this.title = title;
        this.body =  body;
        this.active = true;
    }

    public onConfirm(): void {
        this.active = false;
        this.onClose.next(true);
        this._bsModalRef.hide();
    }

    public onCancel(): void {
        this.active = false;
        this.onClose.next(false);
        this._bsModalRef.hide();
    }

    public hideConfirmationModal(): void {
        this.active = false;
        this.onClose.next(null);
        this._bsModalRef.hide();
    }
}

opening the modal with the modal service from another component:

public showConfirmationModal(): void {
    const modal = this._bsModalService.show(ConfirmationModalComponent);
    (<ConfirmationModalComponent>modal.content).showConfirmationModal(
        'Title of modal',
        'Body text'
    );

    (<ConfirmationModalComponent>modal.content).onClose.subscribe(result => {
        if (result === true) {
            // when pressed Yes
        } else if(result === false) {
            // when pressed No
        } else {
            // When closing the modal without no or yes
        }
    });
}

@nielswitte Thank you. I am using your sample code.

Hi,

am I the only one who thinks this is highly inconvenient? So much boilerplate code for a very common use case. Passing data to the modal was implemented in July (see #2290), so I think that subscribing to a generic result of the modal should be implemented too. To be honest, I like the approach of this little npm package here: https://www.npmjs.com/package/ng2-bootstrap-modal but that is just a suggestion.

@valorkin Any chance something like this finds its way into ngx-bootstrap?

@denniseffing I would say chances are 100% :)

Thanks for the update, I really appreciate it. Let me know when you plan on working on it in the future.

I have something around 50-60 items in todo list for v2 :)

one of them is rewrite 90% of code base, to increase readability and performance :D

That doesn't sound very promising for a recent update but oh well, best of luck. If you point me into the right direction for this feature, I can consider creating a pull request.

Without confirmation component continue work and i don't want it
After confirmation its execute next line

The onClose observable is not resolved on keyboard exit (esc). Does anyone know how to capture this event?

@nielswitte , thanks sir. This is a great solution.

Has anything been done in v2 to make this less boiler plate intensive? I'm looking for a simple way to indicate that a modal was closed by successfully performing a operation built within the component of the modal. Thanks!

I'm looking for a easy way to notice the controller who opened the modal that the modal is close with confirm button or cancel button, Thanks!

What if the show() method could return an observable that emits a literal with user-specified property (name of the emitter being observed).

Something like:

const modal = this.bsModalService.show(ConfirmationModalComponent, {observe: 'onClose'})
subscribe(response => {
  // response could be anything:
  // {onClose: true} - simple boolean
  // {onClose: {title: 'abc'}} - form value
})

I would personally be happy with this syntax. Would that be possible?

Was this page helpful?
0 / 5 - 0 ratings