How we can set default route in NUXTJS - vue.js

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".

Related

Redirect with page reload Vue JS Router

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

how to redirect to child route in nuxt?

i want to redirect to child route, if user entered to localhost:3000/browse,
he redirect to localhost:3000/browse/songs/new.
but i don't know how to do it!
and i don't know what is the best component structure for this example
my routes will be like this:
localhost:3000/browse/songs/new
localhost:3000/browse/songs/popular
localhost:3000/browse/songs/top
localhost:3000/browse/songs/podcasts
localhost:3000/browse/songs/playlist
and in all of theme, i have a common section, but contents are difrent.
common section
If you only have one location to redirect to, check out Andrew1325's answer. If there are multiple route-to-redirect match-ups, this thread has some ideas.
The way I do it is with "anonymous" middleware, like so:
In /pages/browse/index.js
<script>
export default {
middleware: [
function({ redirect }) {
redirect('/browse/songs/new');
},
],
};
</script>
To redirect automatically or under certain conditions you need to use middleware. This can be setup like this:
//browse/index.js
<template>
//no need for content as redirecting
</template>
<script>
export default {
middleware: 'redirect'
}
</script>
and your middleware file...
//middleware/redirect.js
export default function ({ store, redirect }) {
// automatic redirect
return redirect('/browse/songs/new')
}
Read about middleware here
Your pages structure is set up in the pages folder and you name folders and pages as you would like your routes to be.
Read about it here
To use a common theme you can use layouts. These will have a <nuxt-child/> section which will display the individual page content.
You can read about them here
All of this is pretty basic nuxt stuff, you should take some time to read the documantation or look at some tutorials listed here.
Big ups to #parker_codes, there is a little deficiency is his implementation which is circular redirection a.k.a forever redirect loop.
To solve this, add some checks in the parent component. This is because Nuxt Js calls the middleware of a parent route anytime a child route is visited.
//browse/index.js
<template>
//no need for content as redirecting
<NuxtChild />
</template>
<script>
export default {
middleware({ route, redirect, from }) {
if(route.path == "/browse" || route.path == "/browse/"){
return redirect("/browse/songs/new")
}
}
}
</script>

Nuxt - How to find the previous route?

I am able to use this.$router.go(-1) to redirect a user to the previous route. However, I am not able to understand how I get get the information about the previous route before redirecting.
Basically, by first reading what the previous route was, I want to make sure that the previous route was from the same domain and only then redirect to it, otherwise do something else.
in nuxt static methods where you have access to nuxt context ex: asyncData or middlewares :
asyncData({from}){
// do something with from
}
but if you want to get the prev route in vue instance you can use
this.$nuxt.context.from
also, remember that from can be undefined if there wasn't any prev page in the browser history
In your page you can add asyncData hook which have access to context object with from property:
asyncData({ from }) {
console.log(from);
}
You can achieve this by implementing the Vue Navigation guards, on the component/page.
<script>
export default {
beforeRouteEnter(to, from, next) {
console.log(from)
next()
},
data() {
return {
...
prevRoute: null,
}
}
}
</script>
Or there is this guy https://gist.github.com/zolotyx/b4e7fda234b3572fb7adaf11391f8eef#file-auth-js, he has made a script to help in redirecting
There is no out of the box way to get this information.
What you can do is attach a beforeRouteEnter as a global guard and save the route before navigating to a new route.
Then you can check to see if there is a previous route saved and execute this.$router.go(-1)
If you are using the router in history mode you could be tempted to use the History api that vue-router is using to get this information. But HistoryApi doesn't allow for this as this would be a huge privacy problem. You could see the entire history of the user in the current tab.
In the [middleware] directory you can put this script [routing.js]:
/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function (context) {
// current route
console.log('route=', context.route.name)
// previous route
if (process.client) {
const from = context.from
console.log('from=', from)
}
}
In [nuxt.config.js]:
router: {
...
middleware: 'routing'
},
Whenever you change the current page in the client you should see a log showing the previous page. Maybe it can help you.

Why console.log() outputs in middleware are only visible on the server when entering page directly?

I tried to test if I can output something in the middleware only on certain processes. But if I use the following code - process.server seems always to work - also when I enter the route directly via browser. Other outputs are only visible when I change the route via router. I'm using Nuxt in the universal mode. What's happening there?
Actually I want to feed the store from localstorage user data and then redirect the user when this page is a guarded one. This could be only done from process.client where localStorage is defined. Can it be done with middleware at all? And also when entering the page directly?
middleware/test.vue
export default function (context) {
if (process.server) {
console.log('MIDDLEWARE SERVER')
}
if (!process.server) {
console.log('MIDDLEWARE NON-SERVER')
}
if (process.client) {
console.log('MIDDLEWARE CLIENT')
}
if (process.browser){
console.log('MIDDLEWARE BROWSER')
}
}
pages/test.vue
<template>
<h1>Some test Template</h1>
</template>
<script>
export default {
middleware: ['test']
}
</script>
After digging deep into this I found an answer from a Nuxt team member. Obviously this is the intended default behavior of middleware in the universal mode to run on page refresh only on server. The documentation wasn't that clear about it.
The only way to get stored data in the page refresh scenario is to use cookies like this.
//middleware/auth.js
export default function(context) {
context.store.dispatch("initAuth", context.req)
}
Then:
//store/index.js
actions: {
initAuth(vuexContext, req) {
if(req) {
if (!req.headers.cookie) {
return
}
// go get the cookie ;)
}
}
}

Aurelia: change navigation in app.js from view

I have an Aurelia project with navigation in app.html and app.js. The project includes a home page that has a different style to it, including navigation that is different than the non-home page views.
I would like to turn off navigation for the home view so I tried setting a variable (showMenu) to toggle the visibility. In fact, I am able to use jQuery to do this, but I wonder if there is an Aurelia way of doing it. If I set this.showMenu to true it shows the menu container, and false hides it. Like this for example:
app.html
<div class="container" if.bind="showMenu">
app.js
constructor(router){
this.router = router;
this.showMenu = true;
...other things
}
What I would like to do is set showMenu to false from home.js. I tried this (among 20 or so other attempts), but it does not work.
home.js
activate() {
this.showMenu = false;
}
Is there a way through $parent or some other means to hide the menu in app.html using a view model?
EDIT
This works but it feels a little like a hack.
home.js
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class Home {
constructor(router) {
this.router = router;
}
attached(){
$("#navbarMenu").hide();
this.router.refreshNavigation();
}
}
You should be able to use router to achieve that. Since this is required for one page only, you can have something like this assuming your route name is home (or you could use other properties of RouteConfig that you have set in configureRouter):
<div class="container" if.bind="router.currentInstruction.config.name !== 'home'">
I approach this problem by using separate shells. By default Aurelia will start your app with app.js (or ts). But you can change that default and also use the same command to redirect to a new shell after authentication.
In your main.ts (or .js) you will have a line to start your aurelia app:
aurelia.start().then(() => aurelia.setRoot());
This line is telling aurelia to start and to set the root view model for your app, when aurelia.setRoot() has no value given it defaults to app.ts (or .js).
So I create a landing for my app where I can display with the page and styles I wish completely separately from the main app, including a limited router and navigation.
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
if (environment.debug) {
aurelia.use.developmentLogging();
}
if (environment.testing) {
aurelia.use.plugin('aurelia-testing');
}
aurelia.start().then(() => aurelia.setRoot('authPage'));
}
authPage.ts is my usual app.ts with a router configuration but it will only have the authPage configured in it and perhaps one or two other welcome pages.
The authPage takes care of authentication and obtaining appropriate tokens. I use a 3rd party for authentication services so all I have on this page is a link. Either way after successful authentication is confirmed you now just want to redirect to an alternative aurelia shell.
#autoinject
export class AuthPage {
private app : Aurelia;
private router : Router;
constructor(router : Router, app: Aurelia) {
this.app = app;
this.router = router;
}
authenticate {
//some kind of authentication procedure...
if(authenticationSuccess) {
this.router.navigate('/', { replace: true, trigger: false});
this.router.reset();
this.router.("authenticatedApp");
}
}
The lines this.router.navigate('/', { replace: true, trigger: false}); and this.router.reset(); are provided to deal with issues mentioned here and also on SO here. The shell switch line this.router.("authenticatedApp"); doesn't work for me without the other two.
My authenticatedApp configures a full router and navigation menu for the user in just the same way as you would normally do with app.ts but now separated into its own shell.
Of course there is nothing to prevent someone linking straight to authenticatedApp but at this point there is no data displayed without an api call which all require an access token to be presented.
This is a useful link on building an Aurelia app with multiple shells for authentication.
The end result is a separated landing pages and application pages which can have different styles and different navigation.On logout you can do the same thing in reverse to reload the auth page.