Stop modal close animation

Is it possible to not do the closing animation on a modal? I have an initial screen where the user can click signup or login which triggers a modal either way. Once they click on the login or create account button it takes them to the logged in, tabbed state of the app. I HAVE to dismiss the modal to get this all to work so it looks funny because you have the top to bottom modal animation AND the right to left animation navigating into the logged in screen. Would be cool if I could dismiss the modal without animation so the only one would be navigating to the logged in screen. I didn’t see anything in the API’s for this.

You can disable the modal animation by setting the animated property to false. Note that this will disable both the opening and closing animations. Here is an example:

await modalController.create({
  animated: false,
  ...
});

You can also provide a custom “empty” close animation via the leaveAnimation property if you just want to disable the closing animation. Here is an example:

import { createAnimation } from '@ionic/vue';

...

await modalController.create({
  leaveAnimation: () => createAnimation(),
  ...
});

Both properties are covered in our documentation for ion-modal: https://ionicframework.com/docs/api/modal#properties

2 Likes

Ok the second solution works. But now that I see no animation, I realize it’s not the modal closing that I don’t like, it’s the transition from right-to-left once logged in that I don’t like. Is there a way to disable that? I also think my call is not the best since it’s from the previous version of Vue:

this.$router.push({ path: '/tabs/home' });

Can I stop the animation in that line? Is that the right way to navigate in Vue 3/Ionic now?

You can disable that as well. It depends on what you are trying to do. Do you want to disable all page transitions or just a page transition on a particular page?

If you want to disable all page transitions inside of a router outlet, you can set :animated="false" on ion-router-outlet: https://ionicframework.com/docs/api/router-outlet#properties

If you want to disable a particular page transition you can use the router-link and router-direction properties on components like ion-button and ion-item: https://ionicframework.com/docs/api/button#properties

<ion-button router-link="/products/123/view" router-direction="root">View Product</ion-button>

router-direction specifies the direction of the transition, so router-direction="root" will result in no animation.

I’ve used ‘router-direction’ before but the problem is my button calls a method because I need to close the modal too. So how can I do this within a method?

Can you show me what you are trying to do in a GitHub repo?

I click a button which calls the login method below:

<ion-button expand="block" @click="login()">Login</ion-button>

async login() {
	if (validateFirebaseLogin()) {
		modalController.dismiss({ animated: false, action: 'login' });
		this.$router.push({ path: '/tabs/home' });
	} else {
		const alert = await alertController.create({
			header: 'Login incorrect. Please try again.',
			buttons: ['OK'],
		});
		return alert.present();
	}
},

Notice the line this.$router.push({ path: '/tabs/home' });. Is that correct? How can I stop animation there?

There isn’t an easy way to override the animation currently when using the raw Vue Router API. As a workaround you could get a reference to ion-router-outlet and set animated = false before this.$router.push and set it back to animated = true after.

Any idea what that code might look like? Still learning the internals so not familiar with being able to access ion-router-outlet yet.

I can think of 2 approaches:

  1. Use a document.querySelector:
let routerOutlet = document.querySelector('ion-router-outlet');
routerOutlet.animated = false;
this.$router.push(...);
routerOutlet.animated = true;

Just make sure you are selecting the correct router outlet if you have an app with multiple ion-router-outlet instances.

  1. Use a ref:

In App.vue:

<template>
  <ion-app>
    <ion-router-outlet ref="routerOutlet"></ion-router-outlet>
  </ion-app>
</template>

<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
  setup() {
    const routerOutlet = ref();
    return { routerOutlet }
  }
});

Depending on your application setup, you will need to find a way to pass this ref to your modal component.

As a quick workaround, I would probably try the first approach and see if that works.

1 Like

Awesome, I did not know of either of those techniques! Thank you for taking the time to share!

1 Like

This is my approach to disable animation in some routes.

<template>
  <ion-app>
    <ion-router-outlet :animated="isRouterAnimated" />
  </ion-app>
</template>

<script>
import { IonApp, IonRouterOutlet } from "@ionic/vue";
import { defineComponent, watchEffect, ref } from "vue";
import { useRoute } from "vue-router";

export default defineComponent({
  name: "App",
  components: {
    IonApp,
    IonRouterOutlet,
  },
  setup() {
    const route = useRoute();
    let isRouterAnimated = ref(true);

    /* Disable animations for the following routes */
    const disabledAnimatedRoutes = ["login", "signup"];

    watchEffect(() => {
      disabledAnimatedRoutes.includes(route.name)
        ? (isRouterAnimated.value = false)
        : (isRouterAnimated.value = true);
    });

    return {
      /* Data */
      isRouterAnimated,
    };
  },
});
</script>

Nice approach! Now do you know a way to adjust the animation instead of stopping? Specifically a routerDirection=back type animation?

you could just use vue animations after you have turned off ion-router animations?