How can I pass and receive data to/from an ngx-bootstrap modal?

Marcos Dimitrio picture Marcos Dimitrio · May 7, 2018 · Viewed 7.8k times · Source

Passing data to a modal can be done using the initialState, but how can I receive data back? For instance, if I want to create a confirm dialog box?

Answer

Marcos Dimitrio picture Marcos Dimitrio · May 7, 2018

Even though there's currently no built-in way to do that, it can be done by binding to the onHide/onHidden events.

The idea is to create an Observer that will subscribe to the onHidden event and fire next() when it receives data from it.

I'm using the onHidden instead of the onHide so all CSS animations are done before the result is returned.

Also I implemented it in a MessageService to keep a better separation of the code.

@Injectable()
export class MessageService {
    bsModalRef: BsModalRef;

    constructor(
        private bsModalService: BsModalService,
    ) { }

    confirm(title: string, message: string, options: string[]): Observable<string> {
        const initialState = {
            title: title,
            message: message,
            options: options,
        };
        this.bsModalRef = this.bsModalService.show(ConfirmDialogComponent, { initialState });

        return new Observable<string>(this.getConfirmSubscriber());
    }

    private getConfirmSubscriber() {
        return (observer) => {
            const subscription = this.bsModalService.onHidden.subscribe((reason: string) => {
                observer.next(this.bsModalRef.content.answer);
                observer.complete();
            });

            return {
                unsubscribe() {
                    subscription.unsubscribe();
                }
            };
        }
    }
}

The ConfirmDialogComponent looks like this:

export class ConfirmDialogComponent {
    title: string;
    message: string;
    options: string[];
    answer: string = "";

    constructor(
        public bsModalRef: BsModalRef,
    ) { }

    respond(answer: string) {
        this.answer = answer;

        this.bsModalRef.hide();
    }

}

After implemented, using it is very straight-forward:

confirm() {
    this.messageService
        .confirm(
            "Confirmation dialog box",
            "Are you sure you want to proceed?",
            ["Yes", "No"])
        .subscribe((answer) => {
            this.answers.push(answer);
        });
}

You can get the full code and see it running in this demo.