skip to Main Content

Given is a VueJS 3 application, based on Quasar and I am struggling to use the Router programmatically.

The issue is described best like this:

1. The Problem

When I push the User to another route, only the URL in the browser will be updated, but the corresponding Component will not get rendered.
I have to manually refresh the web page in the Webbrowser in order to get the corresponding component rendered properly.

2. Code

I have published a full working example on GitHub: https://github.com/itinance/quasar-router-bug

The router is configured in history-mode, but this doesn’t matter as the issue appears also in the hash-mode.

Here are my routes:

import { RouteRecordRaw } from 'vue-router';

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    component: () => import('layouts/MainLayout.vue'),
    children: [{ path: '', component: () => import('pages/IndexPage.vue') }],
  },

  {
    path: '/test',
    name: 'test',
    component: () => import('layouts/MainLayout.vue'),
    children: [{ path: '', component: () => import('pages/TestPage.vue') }],
  },

  // Always leave this as last one,
  // but you can also remove it
  {
    path: '/:catchAll(.*)*',
    component: () => import('pages/ErrorNotFound.vue'),
  },
];

export default routes;

Here is my Index-Component, that contains a button where I want to send the user programmatically to another page:

<template>
  <q-page class="row items-center justify-evenly">

    <div class="q-pa-md example-row-equal-width">
      <div class="row">
        <div>INDEX PAGE</div>
      </div>


      <div class="row">
        <div>
          In order to navigate to the test page, you need to manually reload the page after clicking the button.
          Otherwise, only a white page will be rendered.

          <q-btn align="left" class="btn-fixed-width" color="primary" label="Go to test page" @click="doRedirect"/>
        </div>
      </div>


    </div>
  </q-page>
</template>

<script lang="ts">
import {Todo, Meta} from 'components/models';
import ExampleComponent from 'components/ExampleComponent.vue';
import {defineComponent, ref} from 'vue';
import {dom} from 'quasar';
import {useRouter} from 'vue-router';

export default defineComponent({
  name: 'IndexPage',
  computed: {
    dom() {
      return dom
    }
  },
  components: {},
  setup() {

    const router = useRouter();

    const doRedirect = () => {
      console.log('doRedirect');
      router.push({name: 'test'});
    }
    return {doRedirect};
  }
});
</script>

And this is the test-component, which is the target component where I want to use send:

<template>
  <q-page class="row items-center justify-evenly">

    <div class="q-pa-md example-row-equal-width">
      <div>
        TEST PAGE

        this will only be rendered after manual page-reload

      </div>
    </div>
  </q-page>
</template>

<script lang="ts">
import { Todo, Meta } from 'components/models';
import ExampleComponent from 'components/ExampleComponent.vue';
import { defineComponent, ref } from 'vue';

export default defineComponent({
  name: 'TestPage',
  setup () {
    return { };
  }
});
</script>
  1. What happens instead?

3.1 This is the index page, containing the button that shall send the user to another page:

enter image description here

3.2. When I click on the Button, the URL will be updated correctly but the test-component won’t get rendered at all:

enter image description here

3.3. But when I refresh the web browser now manually (or navigate to that particular URL), it will render the test component:

enter image description here

#4. Question

What am I doing wrong? How can I programmatically send the user to the test-page so that not only will the URL be updated but also the component will get rendered automatically, once the URL has changed?

As already mentioned, I also published a small test project that makes the described issue reproducible: https://github.com/itinance/quasar-router-bug

2

Answers


  1. Not an answer, but an ugly workaround: I ran into this issue 3 years ago and couldn’t find any help using router.push. But since <router-link :to> worked as expected, I used a Modal with a button to force the user to click on the button in order to navigate to the destination route. Not the best UI, but it has worked out properly and has still been live in production since 2020

    Login or Signup to reply.
  2. /test should be another child route of / since both IndexPage and TestPage are meant to be rendered in the same <router-view /> that is in MainLayout.

    const routes: RouteRecordRaw[] = [
      {
        path: '/',
        component: () => import('layouts/MainLayout.vue'),
        children: [
          { path: '', component: () => import('pages/IndexPage.vue') },
          {
            name: 'test',
            path: '/test',
            component: () => import('pages/TestPage.vue'),
          },
        ],
      },
      {
        path: '/:catchAll(.*)*',
        component: () => import('pages/ErrorNotFound.vue'),
      },
    ];
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search