Redirect with page reload Vue JS Router - vue.js

I have an app with a Login.vue and Home.vue files. Because I converted an admin HTML website to a vue 3 app, my javascript only works with page reload. When creating the app I selected add router for SPA maybe I shouldn't have. Up to this point, the views are working except when I redirect from login to home without reloading. Since it is not reloading, my navbar or any JS-dependent functions won't work. how do I redirect from login to home with page reload? Currently, I have the below code but still not working.
this.$router.push({
path: "/admin/home",
reload: true
});

You can use this.$router.go() with empty arguments to reload the page. In combination with this.$router.push({ path: '/admin/home' }) you can achieve it without using vanilla JS features.
<template>
<button #click="redirectReload">Redirect & Reload</button>
</template>
<script>
export default {
methods: {
redirectReload() {
this.$router
.push({ path: '/expedition' })
.then(() => { this.$router.go() })
}
}
}
</script>
Notice how I used .then after $router.push(). Without then the page reloads too quickly, leaving no time for the route to change.
As a bonus, it lets you use all the features of $router.push (for example using arguments like { name: 'home' }.

Vue Router not reload page when you navigate to new URL.
You can try this code for you issue:
const url = new URL('/admin/home', window.location.origin)
window.location.href = url.toString()
Hope this help

Related

How to manually generate pages in Nuxt router with a 404 page fallback for .htaccess

I'm trying to create an SSG site with Nuxt.js.
When I access a route that isn't set in the generate property of nuxt.config.js,
I want to display the contents of a 404 page without changing the URL.(using htaccess)
The following is the site under construction
http://we-are-sober.d3v-svr.com/xxxx
This is working as expected.
http://we-are-sober.d3v-svr.com/user/xxxx
This does not work as expected.
The contents of page 404 are displayed for a moment, but soon after that, the process based on the dynamic route of "user/_id.vue" is executed.
The point of the problem is that the non-existent route behaves as if it exists.
Does anyone know how to solve this problem?
Here is the source code.
https://github.com/yhirochick/rewrite_test
404.vue
https://github.com/yhirochick/rewrite_test/blob/master/pages/404.vue
user/_id.vue
https://github.com/yhirochick/rewrite_test/blob/master/pages/user/_id.vue
nuxt.config.js
https://github.com/yhirochick/rewrite_test/blob/master/nuxt.config.js#L43-L45
.htaccess
https://github.com/yhirochick/rewrite_test/blob/master/static/.htaccess
I am Japanese. The above text is based on Google Translate.
It may be difficult to understand, but thank you.
My way of handling this kind of issue while minimizing the API calls required are following those steps:
generate a brand new Nuxt project
install axios: yarn add -D axios
add this to the nuxt.config.js file
import axios from 'axios'
export default {
...
generate: {
routes: async () => {
const users = await axios.get('https://jsonplaceholder.typicode.com/users')
return users.data.map((user) => ({
route: `/users/${user.id}`,
payload: user,
}))
},
fallback: 'no-user.html', // this one is not needed anymore if you ditch the redirect!
},
}
This will generate all the needed routes, while keeping the calls to a minimum thanks to payload that will be passed later on to the pages. More info can be found in the docs.
then, creating the /pages/users/_id.vue page does the trick
<template>
<div>
<div v-if="user">User name: {{ user.name }}</div>
<div v-else-if="error">{{ error }}</div>
</div>
</template>
<script>
export default {
asyncData({ payload }) {
if (payload && Object.entries(payload).length) return { user: payload }
else return { error: 'This user does not exist' } // this will also catch users going to `/users/`
},
}
</script>
create some no-user.vue page, error.vue layout and you should be gucci
At the end, we have 10 users from the mocked API. So those are the following cases:
if we go to /users/5, the user is already static so we do have it's info without any extra API call
if we go to /users/11, the user was not present at the time of build, hence he is not here and we are displaying an error
if we go to /users, we will still be sent to the /pages/users/_id page, but since the :id will be optional there, it will error and still display the error, an index.vue can of course handle this case
My github repo for this one can be found here: https://github.com/kissu/so-nuxt-generate-placeholder-users
This approach is called full static in Nuxt, as explained here: https://nuxtjs.org/announcements/going-full-static/
It's a tricky way, but I've found the code that works as I want.
https://fes.d3v-svr.com/users/xxxxxx
It's works that I expect.
User xxxxxx doesn't exist
Display 404 page
The URL /users/xxxxxx as it is
First, simply set .htaccess to rewrite non-exist page to 404 page
ErrorDocument 404 /no-user/index.html
Only above, Nuxt execute base on URL /users/xxxxxx/ and re-render the page as "UserXXXXXX" even he is not exist.
To avoid this, users/_id.vue is like bellow.
template
<template>
<div v-if="ssr">User name: {{ user.name }}</div>
</template>
script
<script>
export default {
asyncData({ payload }) {
return { user: payload, ssr:true }
},
}
</script>
It seems to be if a template is empty, nuxt will not execute the script depends on the URL.
It's very tricky, so I'll continue to how it is works.

How we can set default route in NUXTJS

How we can customize NUXT routing. Currently, I am working with the default NUXT page routing mechanism. I want to point example.vue as the default landing page instead of index.vue. I also need to add authentication on these routing. unfortunately, NUXT document didn't help me well.
Check to middleware Property on Nuxt
You can write a middleware and call it in your index.vue as:
middleware: {
'redirect-to-example'
}
middleware/redirect-to-example.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect(301, '/example');
}
}
You find useful informations about The Context to play well with Nuxt
To change the landing page you can use the following pages/index.vue:
<template>
</template>
<script>
export default {
created() {
this.$router.push('/example')
},
}
</script>
when the user navigates to https://localhost:3000 the route /projects will be pushed and the url will change to https://localhost:3000/example, this can be seen as an internal "redirect".

Vue URL Updating but Component is not

Having an issue with my url updating but the page not.
From the home page, I display a list of projects. Clicking a project will take you to "website.com/project/project-1" and everything works as intended.
However, at the bottom of that page, I again show a list. This list is the same as homepage, with same functionality. But the problem is, is that it will update the url to "website.com/project/project-2" but the page will not re-render or change.
An example of my code
My current router-path of the component.
path: '/project/:project_slug',
name: 'ProjectPage',
component: ProjectPage
My Router Link from the project page to the new project page
<router-link :to="{ name: 'ProjectPage', params: {project_slug: projectHighlightSlug} }">
<h4 class="header-17 semibold">{{projectTitle}}</h4>
</router-link>
Update
This is my current method/watch section
methods: {
goToProject() {
this.$router.push({
name: 'ProjectPage',
params: {project_slug: this.projectHighlightSlug}
})
},
},
watch:{
// eslint-disable-next-line no-unused-vars
'$route'(to, from) {
this.goToProject();
}
}
However, the to,from is "defined but never used" and clicking my button to call goToProject() gives me the error;
"You may have an infinite update loop in watcher with expression "$route""
As explained in the Vue Router docs, when the url the user navigates to uses the same component, it uses the same instance of that component. The docs therefore recommend to listen to $route changes or to use the beforeRouteUpdate navigation guard.
You need to watch the routes to update your page. see code below
watch:{
'$route' (to, from) {
this.goToProject()
// call your method here that updates your page
}
},
source dynamic route matching

Vue router reloading the current route

Without reloading the whole page I need to reload the current route again (Only a component reload) in a vue app.
I am having a path in vue router like below,
{
path: "/dashboard",
name: "dashboard",
component: loadView("Dashboard"),
},
When user clicks on the Dashboard navigation item user will be redirected to the Dashboard page with vue router programmatic navigation
this.$router.push({ name: "dashboard" });
But when user already in the dashboard route and user clicks the Dashboard nav item again nothing happens. I think this is vue router's default behaviour. But I need to force reload the Dashboard component (Not to refresh the whole page).
I can't use beforeRouteUpdate since the router is not updated. Also I have tried the global before guards like beforeEach. But it is also not working.
How can I force reload the dashboard component without reloading the whole page?
It can be done in two ways.
1) Try doing vm.$forceUpdate(); as suggested here.
2) You can take the strategy of assigning keys to children, but whenever you want to re-render a component, you just update the key.
<template>
<component-to-re-render :key="componentKey" />
</template>
<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>
Every time that forceRerender is called, the prop componentKey will change. When this happens, Vue will know that it has to destroy the component and create a new one.
What you get is a child component that will re-initialize itself and “reset” its state.
Not mentioned here, but as the offered solutions require a lot of additional work just to get the app to render correctly, which imo is a brittle solution.. we have just implemented another solution which works quite well..
Although it is a total hack.
if (this.$route.name === redirect.name) {
// this is a filthy hack - the vue router will not reload the current page and then have vue update the view.
// This hack routes to a generic page, then after this has happened the real redirect can happen
// It happens on most devices too fast to be noticed by the human eye, and in addition does not do a window
// redirect which breaks the mobile apps.
await this.$router.push({
name: RouteNames.ROUTE_REDIRECT_PLACEHOLDER
});
}
... now continue to do your normal redirect.
Essentially, redirect to a placeholder, await the response but then immediately continue to another page you actually wanted to move toward

Vue.js with VueRouter - how to correctly route on user's refresh

I use Vue and VueRouter (and also Vuex but it is not the case here) in my project. Imagine i have 5 files:
main.js - stores all components definitions, imports them from
external files and so on.
App.vue - it is main component that stores
all other
routes.js - stores all the routing definitions
login.vue -
stores login component (login page)
content.vue - stores page
component
(quite simplified version but you surely get the idea).
Now if i open my path '/' it should reroute me to '/login' page if i am not logged in and to '/content' when i am logged in. Nothing special here.
Now my page works as intended (almost). If I enter in my browser '/content' it tries to render '/content' component with default data (ie userId = -1), then immediately it reroutes me to '/login' page. The '/content' shows just for a second. And it is my problem. I would like to reroute to '/login' without earlier rendering '/content' with default data.
It is obvious that it tries to render '/content' - maybe from cache or something, but since rerouting is my first command in created() it should not
mount /content component in app component, but /login.
Any idea how to prevent it?
I am aware that i do not attach any code, but i hope it wont be necessery for you to understand the problem and advice any solution because it would need cutting and simpliding a lot of code.
In your case, I think you should use vue router's beforeEach hook.
You can use meta field in router to indicates whether the path need authentication, and do processing in beforeEach function.
I will give the sample code.
import Router from 'vue-router';
const router = new Router({
routes: [{
path: '/content',
meta: {
auth: true,
}
}, {
path: '/login',
}]
});
router.beforeEach(async (to, from, next) => {
if (to.matched.some(m => m.meta.auth)) {
// user your authentication function
const isAuth = await getAuthentication;
if (!isAuth) {
next('/login');
}
next();
}
})
if your authentication function is not async function, you should remove async/await keywords
Except if the API in the meantime declares that you are no longer authenticated, the router will not be able to refresh itself by the beforeEach method.
Even with a loop method that retrieves data from the API, which will store them in the store as reactive data.
In Vue everything can be reactive, except Vue router