Error message after call of menuController.open() on ion-menu: "ASSERT: can not be animating"

Hi there,

really … simple question, very simple task …

I use that new Ionic 7 framework as a Vue-project. I seem to don’t know how to call the open() method on ion-menu. All I want to do is open the ion-menu programatically, described in the components documentation. Here’s a reduced version of my code …

Could please someone just show me, how I have to call open(), but without the error message in the console: “ASSERT: can not be animating”?

App.vue:

<template>
  <ion-app>

    <ion-menu menu-id="app-menu" content-id="main-content">
      <ion-header>
        <ion-toolbar>
          <ion-title class="ion-text-center">
            A Title ...
          </ion-title>
        </ion-toolbar>
      </ion-header>
      <ion-content class="ion-padding">
        <ion-list>
          <ion-item>
            <ion-label>An item ...</ion-label>
          </ion-item>
        </ion-list>
      </ion-content>
    </ion-menu>
    
    <ion-router-outlet id="main-content"></ion-router-outlet>
  
  </ion-app>
</template>

<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import {
  ...,
  IonMenu,
  menuController,
  ...,
} from '@ionic/vue';

export default defineComponent({
  name: 'MainMenu',
  components: {
    ...,
    IonMenu,
    ...,
  },
  setup() {
    onMounted(() => {
      menuController.open('app-menu'); // Result as expected, but error message in console: ASSERT: can not be animating
    })

    return {
    }
  }
});
</script>

No chance to get rid off this error message? Sorry, I’m asking again, but it’s a so simple task, I’m just confused … :confused:

  1. The argument taken by menu.open() is a boolean value whether or not the menu animates. Not the ID of the menu Ion Menu docs

  2. I am not a vue expert but I think you want to make a template ref in that ion-menu (ref="myMenu"), then, target that in your onMounted() with await this.$refs.myMenu.open()

Let me know if that is right!

Hi, thanks for your reply.

To 1.: I am using the open() method of the const “menuController”, not the open() method of the ion-menu component I’m asking for, like it’s described in the documentation. See picture below at the end of this post.

import {
  ...,
  IonMenu,
  menuController, // <-- This one has another open() method, that wants the menu-id, not a boolean
  ...,
} from '@ionic/vue';

To 2.: Yes, I tried this, too, but when I get the reference to the ion-menu element, then the debugger tells me, that he does not know any open() method on that html element.

  • Anyone has clues, how I use the open(animated?: boolean) method shown in the documentation and NOT the open(menu?: string | null) of menuController const?

  • Or even does someone know, when keeping the way over the menuController const, how I get rid of the error message at least?

Thank you jjdev and all :expressionless:

Here … This is the “other” open() method of menuController const, and not the one described in the documentation I’m lookin’ for:

Ok yes I was looking at the wrong open()

For the menu controller does it need to be async?

Also should onMounted() be independent from setup() per composition API? Again im not a vue expert

The open() of menu controller has no need to be async, but maybee in the future …

onMounted() is a method used by the “clean” and new composition api of Vue. Under the hood it still uses the separated mounted hook you mention. The fact this method is inside of the setup() method is principially the same like not using the composition api with an own mounted hook and no usage of setup(), instead of data(), methods() and the other Vue component members. To keep it short: You can ignore this thing with the composition api.

Do you know, how I call the open() method shown in the documentation? Or do you know, how I get rid off the error message, when still using open() from menuController?

Again: The open() method of menuController does what I want, but I see that anoying error message in the console … My hope is: If I know, how to use the open() method of the documenation (not the menuController), then I would go the way of best practice (and hope that this error message does not appear, because of the recommended “documentation” way) …

I don’t know, how else I should describe this …

Can you copy and paste the whole error just to see if there’s anything hints?

I found this from ionic 4.x
Assert: cannot be animating

Assert is a unit test keyword so it could be in the test files under the hood that’s throwing that

Here we go :wink:

This means, that’s an issue in the test units of the framework, I can keep the way over menuController’s open() method, and at least I can “ignore” the error message, am I right? Since I don’t have written any test units in my code …

But for real … It does not look very “clean”, especially for my employer or him’s customer, nor like the “best practice” … hrmpf :frowning:

For now, ignoring seems ok if it’s not throwing off your expected outcome

But I would highly recommend bringing it up as an issue on the GitHub, as it seems like a test issue on their end, as well as it was previously added as a bug in older builds with the same error, so they’ve fixed it before

Just another hint, just for fun: I tried to “click” an ion-menu-button element programatically, but the same error appears, when I don’t wait for 25ms with a setTimeout(), before calling the click() handler of the reference of that element or even by documents.querySelector('ion-menu-button').click()

Yes, the ion-menu opened up, but I got still this anoying error message. But one thing: If I waited (just for fun) for minimum 25ms with a setTimeout(), the error did not appear, but that’s not best practice.

So I thought, it must be something like a rendering timing issue. I changed the onMounted() routine to an ionViewDidEnter() routine, but still the same error message (and the ion-menu opened as expected). Here then I waited for 25ms, too, just to see, what happens, and guess what? The error message disappeared, but I must not use a setTimeout(), because this is not the way, it should be done, never ever.

Perhaps I could open the ion-menu by programatically clicking the ion-menu-button element on a more later lifecylce hook then ionViewDidEnter? But is there any one? Or another event I got to listen to?

Just some flippy ideas …

What if you trying importing platform and wrap the first open() call with platform.ready().then(() =>{}) I’m not 100% on the vue syntax…

I wonder if this would achieve the same timing result but within the lifecycle of ionic not a arbitrary timeout

Good point. There is no platform.ready() for VueJs like in Angular … see Platform | Ionic Documentation

The closest thing like platform.ready() is in Vue’s main.ts, like

router.isReady().then(() => {
app.mount(‘#app’);
});

After app.mount() the lifecyle hooks of Vue fires up, like mounted() or onMounted() (for Vues composition api, it’s the same, like mounted …). And after Vue’s lifecycle hooks the one’s of Ionic appears then, like ionViewDidEnter() … It seems, like ionViewDidEnter() is the youngest/last hook that fires, if the app is loaded and page is mounted/build/ready for nasty things …

Here’s a diagram for Vue’s lifecycle hooks: Lifecycle Hooks | Vue.js
And here are the one’s of Ionic with VueJs and the composition api usage: Vue Lifecycle | Ionic Documentation

Maybe try it in ionViewDidEnter()?
Seems like mounted() is definitely too soon if setTimeout() is handling it too

Yes I tried it in ionViewDidEnter() already, but even here I would have to use the timeout to wait for the “animation” …

So this is not the point I should look for. I think I should somehow get an event or smthg, of ion-menu, showing me still running animations processes or their ends of ion-menu, maybee. Or perhaps I have to deactivate/activate the ion-menu somehow, to prevent some errorness, when calling an animated process like open/close. Or somehow a property, in case there are still animated processes running or anything …

And the fun thing is, I could use open(animated: boolean) like listed in the documentation, with its boolean parameter “animated” but I do not know, where this method is. I only found this other open(menuId: string) from the menuController, which seems to be not the same as the one from the documentation.

But I ask myself, where this open() method comes from and how to access it, mentioned in the documentation …

To everyone, especially to @jjev so far, thank you for your audience :slight_smile:

If you could point me to where I can find and how to access the open(animated: boolean) method, mentioned in the ion-menu documentation, which is not the same as the open(menuId: string) method found in the menuController imported from @ionic/vue

BTW, if someone asks for the package.json dependencies:

  "dependencies": {
    "@capacitor/app": "5.0.2",
    "@capacitor/core": "5.0.4",
    "@capacitor/haptics": "5.0.2",
    "@capacitor/keyboard": "5.0.2",
    "@capacitor/status-bar": "5.0.2",
    "@ionic/storage": "^4.0.0",
    "@ionic/vue": "^7.0.10",
    "@ionic/vue-router": "^7.0.10",
    "ionicons": "^7.0.0",
    "pinia": "^2.1.3",
    "vue": "^3.3.4",
    "vue-router": "^4.2.2"
  },
  "devDependencies": {
    "@capacitor/cli": "5.0.4",
    "@vitejs/plugin-legacy": "^4.0.2",
    "@vitejs/plugin-vue": "^4.0.0",
    "@vue/eslint-config-typescript": "^11.0.2",
    "@vue/test-utils": "^2.3.0",
    "cypress": "^12.7.0",
    "eslint": "^8.35.0",
    "eslint-plugin-vue": "^9.9.0",
    "jsdom": "^21.1.0",
    "typescript": "^4.9.3",
    "vite": "^4.1.0",
    "vitest": "^0.29.2",
    "vue-tsc": "^1.0.24"
  },

Using open(animated?: boolean) requires the template ref like I was talking about earlier, and calling open directly on that template ref instead of a controller

1 Like

TL;DR
Use

document.querySelector(‘ion-menu’)?.open(false);

if you want to show ion-menu on the start of your app without running into error messages or animation timing issues and without usage of the menuController or VueJs-Refs, where the methods like open/close of the ion-menu documentation are missing :slight_smile:

And now the long part:

Okay then, again: There is no open() method on the ref-reference with vue, but on the direct reference with document.querySelector() … But you are right @jjdev, I found the open() method mentioned in the documentation now:

App.vue:

<template>
  <ion-app>
    <ion-menu content-id="main-content" ref="mymenu">
    ...
</template>

<script lang="ts">
import { ref, defineComponent, onMounted } from 'vue';
import {
  ...
  IonMenu,
} from '@ionic/vue';

export default defineComponent({
  name: 'MainMenu',
  components: {
    ...
    IonMenu,
  },

  setup() {
    const mymenu = ref(null); // null is okay, I return mymenu at the end of setup() and vue catches the reference over the ref=-attribute above in the html

    onMounted(() => {
      mymenu.open(); // no open method
      mymenu.value.open(); // no open method
      document.querySelector('ion-menu')?.open(true); // works, **but** with error message caused by animation timing issue
      document.querySelector('ion-menu')?.open(false); // **SOLVED!!!** -> works, without any error message
    }

    return {
      ...
      mymenu,
    }

SOLUTION:
document.querySelector('ion-menu')?.open(false); is the right way to

  • use the methods in documentation
  • open the ion-menu without animation, to get rid off the error message
  • no need to use the old menuController anymore, as those methods seem to be deprecated, because there’s no parameter for unusage of animations, but the menuId :slight_smile:

Here a screenshot of the Vue-ref from debugger, missing the methods open/close of the documentation:

Here the screenshots of the try to call open() on Vue-ref and it’s value:

This happens, when I call document.querySelector('ion-menu')?.open(true);:

And the solution by using the open() method of the documentation to ion-menu without animation resulting in the expected beahviour and without any timing problems, that throws the ASSERT-error:


document.querySelector('ion-menu')?.open(false); // this is it, yesssss!!!


Nice @jjdev, very good. I can stick with this, customer and employer are happy now, because at this point of the app we don’t need an animation. The ion-menu has to be shown on start of the app, and it’s okay, if it is not animated at this point :slight_smile:

@jjdev you pointed me to the right way, using the ion-menu methods. Thank you very much!

Now I’m hungry …

1 Like

Ok nice the optional chaining maybe helped
I wasn’t sure about using the controller with vue as I’d only seen it in angular

Glad you got it working!