Can't seem to get "beforeRouteUpdate()" to work

Hi all,

I’ve started building an Ionic 5 app based on one of the examples (the one with the menu).

Now, I have worked with Vue in the past, but somehow I can’t get the function “beforeRouteUpdate()” to be called.

Is there something I need to do in Ionic before this function get’s called? I’ve updated all packages with “npm update” to the latest versions.

<script lang="ts">
import { IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
import { defineComponent, ref } from 'vue';
export default defineComponent({
  name: 'Folder',
  components: {
    IonButtons,
    IonContent,
    IonHeader,
    IonMenuButton,
    IonPage,
    IonTitle,
    IonToolbar,
  },
  beforeRouteEnter(){
    console.log('this one is called');
  },
  beforeRouteUpdate (to, from, next) {
    console.log('this one is not!');
    console.log(to, from);
    next();
  }
});
</script>

The function “beforeRouteEnter()” is called. But somehow the “beforeRouteUpdate()” is not. What am I missing?

i think this is used in the router? This doesn’t look like the code for a router…

According to the docs, it is an ‘in-component’ function:
https://router.vuejs.org/guide/advanced/navigation-guards.html#in-component-guards

  beforeRouteUpdate(to, from) {
    // called when the route that renders this component has changed,
    // but this component is reused in the new route.
    // For example, given a route with params `/users/:id`, when we
    // navigate between `/users/1` and `/users/2`, the same `UserDetails` component instance
    // will be reused, and this hook will be called when that happens.
    // Because the component is mounted while this happens, the navigation guard has access to `this` component instance.
  },

according to the documentation, it is called when the route changes… I don’t see in your code where. the route is actually changing?

Hi Aaron,

I am changing the route, the code I posted was a simplified version of my app.

Anyway here is a more elaborate example:

Based on the Ionic tabs example: “ionic start myApp tabs --type vue”

router/index.ts:

import { createRouter, createWebHistory } from '@ionic/vue-router';
import { RouteRecordRaw } from 'vue-router';
import Tabs from '../views/Tabs.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    redirect: '/tabs/tab1'
  },
  {
    path: '/tabs/',
    component: Tabs,
    children: [
      {
        path: '',
        redirect: '/tabs/tab1'
      },
      {
        path: 'tab1/:id?', // I have hadded the ID parameter here!
        component: () => import('@/views/Tab1.vue')
      },
      {
        path: 'tab2',
        component: () => import('@/views/Tab2.vue')
      },
      {
        path: 'tab3',
        component: () => import('@/views/Tab3.vue')
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

In tabs.vue I have added a second page based on tab1 that only has another route parameter:

<template>
  <ion-page>
    <ion-tabs>
      <ion-tab-bar slot="bottom">
        <ion-tab-button tab="tab1" href="/tabs/tab1">
          <ion-icon :icon="triangle" />
          <ion-label>Tab 1</ion-label>
        </ion-tab-button>
          
        <!-- modified the second link to also render the tab1 view with a parameter -->
        <ion-tab-button tab="tab1a" href="/tabs/tab1/a">
          <ion-icon :icon="ellipse" />
          <ion-label>Tab 1a</ion-label>
        </ion-tab-button>
        
        <ion-tab-button tab="tab3" href="/tabs/tab3">
          <ion-icon :icon="square" />
          <ion-label>Tab 3</ion-label>
        </ion-tab-button>
      </ion-tab-bar>
    </ion-tabs>
  </ion-page>
</template>

<script lang="ts">
import { IonTabBar, IonTabButton, IonTabs, IonLabel, IonIcon, IonPage } from '@ionic/vue';
import { ellipse, square, triangle } from 'ionicons/icons';

export default {
  name: 'Tabs',
  components: { IonLabel, IonTabs, IonTabBar, IonTabButton, IonIcon, IonPage },
  setup() {
    return {
      ellipse, 
      square, 
      triangle,
    }
  }
}
</script>

Than I expect in “tab1.vue” the ‘beforeRouteUpdate()’ function to fire. But is is not doing so:

<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>Tab 1</ion-title>
      </ion-toolbar>
    </ion-header>
    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">Tab 1</ion-title>
        </ion-toolbar>
      </ion-header>
    
      <ExploreContainer name="Tab 1 page" />
    </ion-content>
  </ion-page>
</template>

<script lang="ts">
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
import ExploreContainer from '@/components/ExploreContainer.vue';

export default  {
  name: 'Tab1',
  components: { ExploreContainer, IonHeader, IonToolbar, IonTitle, IonContent, IonPage },
  beforeRouteEnter() {
    console.log('enter');
  },
  beforeRouteUpdate(to: any, from: any) {
    console.log(to);
  }
}
</script>

Hi @pkluver

Were you able to solve this one?

For now I’m watching the $route object as per Dynamic Route Matching | Vue Router but would prefer using the beforeRouteUpdate navigation guard.

No I haven’t been able to.
I have a ‘work-around’ for now…