Custom modal / alert (with HTML, form...)

Furthermore to the css, I think the transition should be updated too, because otherwise, the modal still gonna be displayed with a transition “bottom-to-top” inclusive a moving background which, I think, is quite ugly.

Since I tried hours to figure out a nice solution, here’s how to implement an “modal alert style transition” (thx to @onderceylan which explain how to build a custom transition, see Adding custom transitions/custom modal transition)

Basically following transition is a mix of:

  • Modal transition to select the element wrapper (ionic/src/components/modal/modal-transitions.ts)
  • Alert transition for the effect opacity itself (ionic/src/components/alert/alert-transitions.ts)

Here we go, create a new class, like my-special-transition.ts containing following:

    import {Animation, Transition} from 'ionic-angular';
    
    export class ModalAlertPopIn extends Transition {
        init() {
            super.init();
    
            const ele: HTMLElement = this.enteringView.pageRef().nativeElement;
            const backdropEle = ele.querySelector('ion-backdrop');
            const backdrop = new Animation(this.plt, backdropEle);
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
            backdrop.fromTo('opacity', 0.01, 0.3);

            this
            .easing('ease-in-out')
            .duration(200)
            .add(backdrop)
            .add(wrapper);
        }
    }
    
    export class ModalAlertPopOut extends Transition {
        init() {
        super.init();
    
        const ele: HTMLElement = this.leavingView.pageRef().nativeElement;
        let backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
        let wrapperEle = <HTMLElement>ele.querySelector('.modal-wrapper');
        let wrapper = new Animation(this.plt, wrapperEle);

        wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
        backdrop.fromTo('opacity', 0.3, 0);

        this
            .easing('ease-in-out')
            .duration(200)
            .add(backdrop)
            .add(wrapper);
    }
}
    
    export class ModalAlertMdPopIn extends Transition {
        init() {
            super.init();
    
            const ele: HTMLElement = this.enteringView.pageRef().nativeElement;
            const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
            backdrop.fromTo('opacity', 0.01, 0.5);
    
            this
                .easing('ease-in-out')
                .duration(200)
                .add(backdrop)
                .add(wrapper);
            }
        }
    
    export class ModalAlertMdPopOut extends Transition {
        init() {
            super.init();

            const ele: HTMLElement = this.leavingView.pageRef().nativeElement;
            const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
            backdrop.fromTo('opacity', 0.5, 0);
    
            this
                .easing('ease-in-out')
                .duration(200)
                .add(backdrop)
                .add(wrapper);
            }
    }

Then in your app.component.ts declare the new transitions, for example in your constructor:

let isAndroid: boolean = this.platform.is('android');
this.config.setTransition('modal-alert-pop-in', isAndroid ? ModalAlertMdPopIn : ModalAlertPopIn);
this.config.setTransition('modal-alert-pop-out', isAndroid ? ModalAlertMdPopOut : ModalAlertPopOut);

And finally, when you call your modal, just pass the custom transitions name

let modal: Modal = this.modalController.create(MyModal, {
                aParam: this.myParam
            },
            {
                enterAnimation: 'modal-alert-pop-in',
                leaveAnimation: 'modal-alert-pop-out'
            });


        modal.onDidDismiss(() => {
            // Nothing to do
        });

        modal.present();

Enjoy!

4 Likes