The fade class doesn't appear to work on the ngb-modal.
I've looked at trying to apply my own animation to the modal but the modal template is obviously injected into modal dialogue by ng-bootstrap e.g. I don't have access to the modal dialogue. I only have access to the template:
<template #content let-c="close" let-d="dismiss">
<div class="modal-header card-header" style="border-radius: 10px;">
<h4 class="modal-title">Contact Form</h4>
</div>
<div class="modal-body"> </div>
...etc
</template>
I need to apply my animation to the top level dialogue otherwise just bits of the modal animate. If I apply it to the template it blows up.
Any idea how I would animate the whole modal??
Here is simple solution. Just put it in style.css
/* modal animation */
.modal-content{
animation-name: example;
animation-duration: 0.3s;
}
@keyframes example {
0% {transform: scale(0.5)}
75% {transform: scale(1.1)}
100% {transform: scale(1)}
}
You need to add animation css class to global styles and add NgbModalOptions.
styles.css: // or whatever is your global css
.modal-holder{
animation-name: example;
animation-duration: 0.3s;
}
@keyframes example {
0% {transform: scale(0.5)}
100% {transform: scale(1)}
}
modal.component.ts
const modalRef = this.modalService.open(NgbdModalContent, {windowClass: 'modal-holder', centered: true});
Enough talk, you can see example on:
StackBlitz
Here is the exact replica of FADE IN - OUT animation with SLIDE DOWN as of bootstrap 4.x
SOLUTION 1: Initialize animation in constructor
app.component.ts:-
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
constructor(private modalService: NgbModal) {
NgbModalRef.prototype["c"] = NgbModalRef.prototype.close;
NgbModalRef.prototype.close = function(reason: string) {
document.querySelector(".modal-backdrop").classList.remove("show");
document.querySelector(".modal").classList.remove("show");
setTimeout(() => {
this["c"](reason);
}, 500);
};
NgbModalRef.prototype["d"] = NgbModalRef.prototype.dismiss;
NgbModalRef.prototype.dismiss = function(reason: string) {
document.querySelector(".modal-backdrop").classList.remove("show");
document.querySelector(".modal").classList.remove("show");
setTimeout(() => {
this["d"](reason);
}, 500);
};
}
open(basic) {
this.modalService.open(basic);
}
app.component.html :-
<div class="card">
<div class="card-header">
<h4 class="card-title">Basic Modal</h4>
</div>
<div class="card-content">
<div class="card-body">
<div class="row">
<div class="col-sm-12">
<p>Toggle a modal via TypeScript by clicking the button above.</p>
<!-- Button trigger modal -->
<button type="button" (click)="open(basic)" class="btn btn-outline-primary block btn-lg">
Launch Modal
</button>
<!-- Modal -->
<ng-template #basic let-modal>
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel1">Basic Modal</h4>
<button type="button" class="close" (click)="modal.dismiss('Cross click')" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" tabindex="0" ngbAutofocus>
<h5>Check First Paragraph</h5>
<p>Oat cake ice cream candy chocolate cake chocolate cake cotton candy dragée apple pie.
Brownie carrot cake candy canes bonbon fruitcake topping halvah. Cake sweet roll cake
cheesecake cookie chocolate cake liquorice.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="modal.close('Accept click')">Accept</button>
</div>
</ng-template>
<!-- / Modal -->
</div>
</div>
</div>
</div>
</div>
styles.scss :-
// modal animation
@keyframes modal-fade {
from {
top: -50px;
opacity: 0;
}
to {
top: 0;
opacity: 1;
}
}
.modal {
top: -100px;
animation: ease-in-out .3s modal-fade;
&.show {
top: 0;
}
.modal-body {
&:focus {
outline: none;
}
}
}
stackblitz link here
SOLUTION 2: initalize animation in individual modal call
app.component.ts :-
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
constructor(private ngbModal: NgbModal) {}
open(content: any, config?: any) {
let modal = this.ngbModal.open(content, config);
let instance = (modal as any)._windowCmptRef.instance;
setImmediate(() => {
instance.windowClass = "custom-show";
});
let fx = (modal as any)._removeModalElements.bind(modal);
(modal as any)._removeModalElements = () => {
instance.windowClass = "";
setTimeout(fx, 250);
};
return modal;
}
app.component.html :-
<div class="card">
<div class="card-header">
<h4 class="card-title">Basic Modal</h4>
</div>
<div class="card-content">
<div class="card-body">
<div class="row">
<div class="col-sm-12">
<p>Toggle a modal via TypeScript by clicking the button above.</p>
<!-- Button trigger modal -->
<button type="button" (click)="open(basic)" class="btn btn-outline-primary block btn-lg">
Launch Modal
</button>
<!-- Modal -->
<ng-template #basic let-modal>
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel1">Basic Modal</h4>
<button type="button" class="close" (click)="modal.dismiss('Cross click')" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" tabindex="0" ngbAutofocus>
<h5>Check First Paragraph</h5>
<p>Oat cake ice cream candy chocolate cake chocolate cake cotton candy dragée apple pie.
Brownie carrot cake candy canes bonbon fruitcake topping halvah. Cake sweet roll cake
cheesecake cookie chocolate cake liquorice.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="modal.close('Accept click')">Accept</button>
</div>
</ng-template>
<!-- / Modal -->
</div>
</div>
</div>
</div>
</div>
styles.scss :-
// animation style
// --------------------------
.modal {
&.show .modal-dialog {
transition: 0.25s all;
// opacity: 0;
transform: translate(0, -5vh);
}
&.custom-show .modal-dialog {
opacity: 1;
transform: translate(0, 0);
}
.modal-body {
&:focus {
outline: none;
}
}
}
stackblitz link here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With