vue-router does not redirect - vue.js

Despite of multiple posts on the subject I can't find what is going wrong. I been followed this example.
Here is my VueRouter instance.
const router = new VueRouter({
mode: "history",
routes: [
{
path: "/",
component: require("./components/producer-table.vue").default
},
{
path: "/producer/:producerId",
component: require("./components/variable-table.vue").default,
props: true
},
{ path: "*", redirect: "/" }
]
});
If I route to a wrong url programmatically (this.$router.push({path: "/wrong});) I am redirected to http://localhost/.
Everything seems to work fine except that when I set a wrong address in Chrome url bar I get the following message:
Cannot GET /wrong
I would expect http://localhost/wrong to be redirected to http://localhost/. I'm quite new using vue router and I'm must miss something. Any ideas?

This is because your webserver doesn't know GET /wrong should be redirected to the index.html file; from there on, vue-router can take over.
Some examples on how to redirect different web servers;
Apache: htaccess rewrite all to index.html
nginx: Rewrite all requests to index.php with nginx
webpack-dev-server:
/// in your webpack.config
devServer: {
historyApiFallback: {
index: '/'
}
}

Related

vue application in php page with router hotlinking

I am currently building a module for a CMS (Joomla) - the frontend of this module is created with VUE 3 incl. Router. The prototype is already working and can be integrated into the CMS Module. Also the router works. If a link is clicked within the VUE app, the corresponding view is displayed. But if the user is now on a subpage of the VUE App and refreshes it (F5 / Ctrl + F5), the page is not found - i think because it exists only in the Vue Router.
To the URL structure:
domain.tld <-- This is where the Vue application is located.
domain.tld/list-:id/item-:id <-- This is the URL for an ITEM
Now I know that it doesn't work like that because the webserver tries to interpret the URL which it can't because parts of it are from VUE.
Is it possible to reconfigure the vue router to work with parameters instead of a "physical" structure?
from: "domain.tld/liste-:id/item-:id"
to: "domain.tld?liste=:id&item=:id"
i think this could solve the issue but i dont know...
Edit:
When i try to use this in the router it still works but has the same effect because yeah "appname" cannot be found by the server..
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/appname?playlist=:id',
name: 'PlaylistDetails',
component: PlaylistDetails,
props: true
},
{
path: '/appname?playlist=:id&video=:vid',
name: 'Player',
component: Player,
props:true
},
]
You can assign a controller to a wild-card, which always return you Vue app:
$router->addMap('/domain.tld/*', 'VueController');
Another approach would be using a # in your URL. Everything after your # will be ignored by the server.
Based on the information i've got from Roman i have changed the routes and added a 404 to the router which refers to home. The views are now been loaded as "url params".
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/#appname?playlist-:id',
name: 'PlaylistDetails',
component: PlaylistDetails,
props: true
},
{
path: '/#appname?playlist-:id&video=:vid',
name: 'Player',
component: Player,
props:true
},
{
// Match all paths vue2 Use * vue3 Use /:pathMatch(.*)* or /:pathMatch(.*) or /:catchAll(.*)
path: "/:pathMatch(.*)*",
name: "404",
component: Home
}
]
If now someone tries to open a site via directlink he got redirected to home.
There might be a better solution but this works when you are using vue inside another PHP app where you are not able to configure the server.
additional info for 404:
https://qdmana.com/2020/12/20201223195804176T.html
It looks that Hotlinks (directly into a view) are not possible in my scenario.

Nuxt Auth Module - How to create Success Redirect

I'm trying to a page in my nuxt app, where the user is on a dynamic route. On this route he has the possibility to log in and should then be redirected to exactly the same route. For the authentification I want to use the auth0 strategy.
I thought the following line would work:
this.$auth.loginWith('auth0')
.then(() => {
this.$router.push("/the-same-route-im-already-on");
})
But apperently I'm only redirected to my home route "/loggedin". And changing the home redirect in my nuxt.config to false, redirects me to my callback-route "/login"
Right now my nuxt.config.js looks like this:
auth: {
auth0: {
...
},
redirect: {
login: '/',
logout: '/',
callback: '/login',
home: '/loggedin',
}
}
I think the default behavior of rewriteRedirect in nuxt Auth Module, should redirect you to the original guarded route.
rewriteRedirect
If this is not working maybe you could redirect the user to login route manually passing a query like this
this.$router.push({ path: '/login', redirect: 'actualRoute' });
And then check in your login page if redirect is setted and then after login you call $router passing the value of redirect.
I don't know if this will help you, so let me know.

Vue - How to create 404 error page with 404 response code

How can I create 404 error page with 404 response code in Vue? Here is the route for 404.
{
path: "*",
name: "404",
component: load("404"),
alias: "/404"
}
You won't be able to set the HTTP status code in a Single-Page Application - all the routing is done on the same page in the browser so once the page is loaded no more HTTP status codes will be received.
However, if you try to load a non-existent route by directly typing/copying the URL into the address bar of the browser - then you can use nginX (or whatever server software you are using) to signal 404 HTTP status:
server {
error_page 404 /404.html;
location / {
try_files $uri $uri/ =404;
}
}
But this is not a practical/wise approach - basically, you want every non-existent path to be resolved to /index.html so that your SPA is always loaded and once loaded - it will detect that this route does not exist and will render your 404 component.
So your nginX config should look like this:
server {
...
location / {
try_files $uri /index.html$is_args$args;
}
}
The $is_args variable will add ? if $args is not empty while $args will provide the query parameters (if any).
Your route definition looks ok, except that I don't know your load function does, i.e. how it resolves to a Vue component. But in general your code follows the common approach as described in the Vue router docs. Usually you won't need a name or an alias here since this route is not used explicitly. Just put in a component that shows your "not found" content and you should be good to go:
{
path: "*",
component: PageNotFound
}
Since this is very close to the code you provided, please explain what exactly gives you a problem.
Like IVO GELOV wrote, you have to force this on the server. I came across the issue with Apache (IVO GELOV provides help on nginx).
In the vue router (Vue 3):
const routes = [
{
// Your other routes here
// ...
{
path: '/404',
name: '404',
component: Error404,
},
{
path: '/:pathMatch(.*)*',
beforeEnter() { window.location.href = "/404" },
},
]
With the last route item, all non-matched routes will be redirected to /404. I use beforeEnter to avoid creating a component and window.location.href to get out of the Vue application.
In Apache .htaccess:
<IfModule mod_alias.c>
Redirect 404 /404
</IfModule>
This will add a 404 error code to the /404 url.
Then the /404 route from the vue router config will call the Error404 component that you have to define and import like any other Vue component!
This answer is heavily inspired by:
https://stackoverflow.com/a/62651493/14217548

Vue.JS - Both 'history' and 'hash' router?

I'm working on a Vue.Js site and using the Vue-router default mode "hash". So the site URL is something like that:
www.mysite.com/#/Home
This site is already being linked by some mobile apps, and I can't change them. But I have a new requirement and I need to change the URLs to remove the hash (#) from the URL. So I changed the Vue-router mode to "history" and now my site is working without the hash. Like that:
www.mysite.com/Home
The problem is that using the history mode the URL with the hash (#) doesn't work. But for compatibility with the mobile apps that link the site with hash, I still need to make the URL with the hash works.
QUESTION:
How can I use the Vue-router history mode and also keep the URLs with hash working?
I tried the following way at the router/index.js file:
export default new Router({
mode: 'history',
routes: [
{
path: '/Home',
name: 'Home1',
component: Home
},
{
path: '/#/Home',
name: 'Home2',
component: Home
},
...
]})
Using this configuration the URL www.mysite.com/Home works, but the URL www.mysite.com/#/Home doesn't work.
I'm answering my own question based on the comment of the #Ohgodwhy and a question/answer from the vue.js forum that was answered by #nathany.
The solution is to remove the has (#) from the URLs that have the hash, and redirecting it to the URL without the hash. It can be done at the method router.beforeEach().
My router/index.js was something like that:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/Home'
export default new Router({
mode: 'history',
routes: [
{
path: '/Home',
name: 'Home',
component: Home
},
],
})
Then I changed to:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/Home'
var router = new Router({
mode: 'history',
routes: [
{
path: '/Home',
name: 'Home',
component: Home
},
],
})
export default router;
router.beforeEach((to, from, next) => {
// Redirect if fullPath begins with a hash (ignore hashes later in path)
if (to.fullPath.substr(0,2) === "/#") {
const path = to.fullPath.substr(2);
next(path);
return;
}
next();
});
For me I just needed to route external legacy links to current history-mode.
In App.vue mounted:
if (location.hash) {
location.replace(location.hash.replace('#', ''))
}
If you stumble across this...
The currently accepted answer works... But if you have a id link in the root path (for example, /#learn-more), the router redirects to /learn-more and would return a 404.
So, I modified the beforeEach route guard to:
router.beforeEach((to, _from, next) => {
if (to.hash.startsWith('#/')) {
const path = to.fullPath.substring(2);
next(path);
return;
}
next();
});
Why? In hash mode, links are passed as hashes
// console.log(to)
{
fullPath: "/#/contact",
path: "/",
hash: "#/contact",
...
}
...while normal id links (in history mode) give
{
fullPath: "/about#learn-more",
hash: "#learn-more",
path: "/about",
...
}
Looking at hash, the difference between a link to an id and a hash-mode link is #/

Customize the route prefix pattern using Vue-Router

I am trying to use Vue-Router to pattern URLs in my new project so they look just like URLs in an existing (non-Vue) application. Existing application URLs look like this:
/#!page1
/#!page2
My Vue Router currently looks like this:
const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/page1'
},
{
path: '/page1',
component: Assessments
},
{
path: '/page2',
component: Assessments
}
]
})
But, of course, this generates URLs that look like this:
/#/page1
/#/page2
How can I configure my router to mimic the /#!route pattern?
You can use the base option:
base
type: string
default: "/"
The base URL of the app. For example, if the entire single page
application is served under /app/, then base should use the value
"/app/".
https://router.vuejs.org/en/api/options.html#base
I have tried it with your case, it also works with /#!.