I'm working in a 404 error page functionality, I got it to work with:
const router = new VueRouter({
routes: [
// ...
{
path: '*',
component: NotFound,
name: '404',
meta: {page_title: 'Vuejs&Material Demo | 404 NOT FOUND'}
},
]
});
// ... not found something
this.$router.push({name: '404'});
The problem with the above is that the url changes too, but I just want the view (component) to change.
I find very annoying when a simple typo redirects to a http://example.com/404, it makes me type the url again or go from the browser autofill, either way I don't like it.
I was wondering if there is some sort of method/logic to have something like this: https://www.facebook.com/sdfsd/sfsdf/asfasfsafastgtgregre .
Bottom line, I want for the view to change but not the url.
Is there any vue/vue-router way to do this?
This is a little hacky, but you could update the route via the router's history object's updateRoute method:
let route = this.$router.match({ name: '404' });
this.$router.history.updateRoute(route);
Related
I am creating angular application that will handle documentation for my GitHub apps, in more complex way than just readme files. I want to redirect user after clicking in topnav dropdown to selected route, but there's problem with router. (I need to redirect with some parameters, but it doesn't work even with simple path reditect). Those methods redirect to target route for like 1 seconds (like excepted), then user got redirected back to root page.
Code:
/* First element is project name, second is category/part of application name */
choices = ["typing_speed_test", "overview"]
json = json
constructor(private router: Router){}
onProjectClick($event){
this.choices[0] = $event.target.innerHTML.trim();
this.choices[1] = "overview";
this.redirect();
}
onCategoryClick($event){
this.choices[1] = $event.target.innerHTML.trim();
this.redirect();
}
redirect(){
this.router.navigateByUrl("404");
}
Routes:
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'project/:project_name/:category', component: SubpageComponent },
{ path: '404', component: NotFoundComponent },
//{ path: '**', redirectTo: '404', pathMatch: 'full' }
];
Link to gif with problem: https://imgur.com/a/x2mPxvh
Full code in github repo: https://github.com/Dolidodzik/DocsForMyApps (if you used code from here to answer this question, please point that in your answer)
I think I may did some stupid mistake, because I am pretty new in Angular, but I couldn't do it, because every google question showed me solves for ERRORS, when redirect doesn't work at all, not to bugs like in my situation.
You need to remove the href="#" from your anchor links in your navigation bar. It's causing the browser to reload:
<a class="dropdown-item" *ngFor="let item of categories() | keyvalue">
{{item.key}}
</a>
Also this is a bit weird solution:
this.choices[0] = $event.target.innerHTML.trim();
You better just send the item variable in your function call in your template, and you can then read this in your component event handler:
onProjectClick(item){
this.choices[0] = item.key;
this.choices[1] = "overview";
this.redirect();
}
the problem is your lins look like this:
link
default link behavior causes your app reload from the start. you should use [routerLink]="['someUrl']" instead of href. If you need that href in some cases, consider calling $event.preventDefault() to cancel the native browser navigation
So I have this section of my vue-router that's causing an issue:
{
component: Tutorial,
name: "tutorial",
path: "/tutorial/:page?",
redirect: "/tutorial/0",
},
If I remove the redirect, the issue is gone. There's no children for this route path either. Is it not possible to assign a default param value?
If you set a default value in redirect part. It will go to /tutorial/0, next it will redirect to /tutorial/0 again and again...
If you want to set a default param value. You can implement it in the Tutorial component.
For example:
// In Tutorial component
beforeRouteEnter() {
this.$route.params.page = this.$route.params.page ? this.$route.params.page : 0
}
because "/tutorial/0" matches "/tutorial/:page?" too.
Since the router configs is First In First out,
you can define your routes like this
{
component: Tutorial,
name: 'tutorial',
path: '/tutorial/0'
},
{
path: '/tutorial/:page?',
redirect: '/tutorial/0'
}
if the current route matches /tutorial/0, it will render your component. If it doesn't match /tutorial/0, Vue will check if it matches /tutorial/:page? and do the redirection if it matches.
I have a vue app with router set up like:
import index from './components/index.vue';
import http404 from './components/http404.vue';
// module lazy-loading
const panda= () => import(/* webpackChunkName: "group-panda" */ "./components/panda/panda.vue");
// ...
export const appRoute = [
{
path: "",
name: "root",
redirect: '/index'
},
{
path: "/index",
name: "index",
component: index
},
{
path: "/panda",
name: "panda",
component: panda
},
//...
{
path: "**",
name: "http404",
component: http404
}
];
So the panda module is lazy-loaded. However, when I navigate to panda page, a console.log() of this.$route.path in App.vue's mounted() lifecycle only outputs
"/"
instead of
"/panda"
But index page works well, it shows exactly
"/index"
as expected.
So how can Vue router get current path correctly of a lazy-loaded page, when page is initially loaded? Did I miss something?
Edit:
It can, however, catch the correct path after Webpack hot-reloads. It catches "/" on first visit of panda, but after I change something in source code, webpack-dev-server hot-reloads, then it gets "/panda".
So I guess it has something to do with Vue life-cycle.
There is a currentRoute property that worked for me:
this.$router.currentRoute
May be you need to use $route not $router
check here : https://jsfiddle.net/nikleshraut/chyLjpv0/19/
You can also do it by $router this way
https://jsfiddle.net/nikleshraut/chyLjpv0/20/
Use this.$route.path.
Simple and effective.
Hide Header in some components using the current route path.
get current route path using this.$route.path
<navigation v-if="showNavigation"></navigation>
data() {
this.$route.path === '/' ? this.showNavigation = false : this.showNavigation = true
}
If You have similar problem the correct answer is to use router.onReady and then calling your logic concerning path. Below the official Vue router docs:
router.onReady
Signature:
router.onReady(callback, [errorCallback])
This method queues a callback to be called when the router has completed the initial navigation, which means it has resolved all async enter hooks and async components that are associated with the initial route.
This is useful in server-side rendering to ensure consistent output on both the server and the client.
The second argument errorCallback is only supported in 2.4+. It will be called when the initial route resolution runs into an error (e.g. failed to resolve an async component).
Source: https://v3.router.vuejs.org/api/#router-onready
For vue 3 (Composition API)
It can be as simple as route.path if you define the variable route as: const route = useRoute()
Usage example
If you try the following, each time your route path changes it will console log the current path:
<script setup>
import {useRoute} from 'vue-router'
const route = useRoute()
watchEffect(() => console.log(route.path))
</script>
Here is my use case:
When i load url /product/123 i want to load component ProductComponent
This is my setup:
RouterModule.forRoot([
{
path: 'product/:productId',
component: ProductComponent
},
{
path: '**', component: NotFoundComponent
},
]),
Now I have added a resolver to check if that product id exists, so my setup looks like this:
RouterModule.forRoot([
{
path: 'product/:productId',
component: ProductComponent,
resolver: {
productResolver: ProductResolver
}
},
{
path: '**', component: NotFoundComponent
},
]),
My resolver checks if that productId parameter exists via api call. The problem i have is that when productId is not found I want to load NotFoundComponent rather than redirecting to different page (i dont want to change url like angular 2 documentation suggests).
Anyone knows how to do that? if not productId found via resolver load NotFoundComponent without changing url/navigate?
I think all you want to do is skip the location change when you navigate to your NotFoundComponent. I'm assuming you've injected the Router into your resolver and are doing something like this when the ID does not exist:
router.navigate(['someUrl']);
Or you might be using the navigateByUrl method. Either way, you can tell the router not to change the URL:
router.navigate(['someUrl'], {skipLocationChange: true});
Don't see why you'd need to load your component via router settings, I'd put it inside the Component that tries to fetch it from the service, and then if it doesn't get a result back toggle some boolean that controls whether the NotFoundComponent gets shown. Some pseudo-ish code below:
ngOnInit(){
if (this.route.snapshot.params && this.route.snapshot.params['id']){
myService.getTheThingById((success)=>{
this.isFound = true;
},(err)=> {
this.isFound = false;
});
}
Then assuming your NotFoundComponent has a selector in it like 'not-found-component' throw it in the template for the component that's calling the service.
<not-found-component *ngIf='!isFound'></not-found-component>
I once faced this problem.
What I did was, in the component, to create 2 other components (in your case, you have ProductComponent, NotFoundComponent, and the other one you want to navigate to, let's say ArticleComponent)
Then I inserted 2 of the components in the main one :
product.component.html
<app-notFound></app-notFound>
<app-article></app-article>
After that, in your ngOnInit, you see if the parameter is there. If he is, then you log it in a property, let's say isParam = true.
Your template becomes
<app-notFound *ngIf="!isParam"></app-notFound>
<app-article *ngIf="isParam"></app-article>
It may not be the best solution out there, but it worked for me !
I have a pretty simple page right now that I'm just setting up for future development but it's kind of come to a halt now that my URL keeps getting changed.
import shipmentInformation from './shipment-information.vue';
Vue.use(VueRouter);
let router = new VueRouter({
base: '/QuickQuote/QuickQuoteRefactor/',
routes: [
{ name: 'shipmentInformation', path: '/', component: shipmentInformation }
]
});
new Vue({
router
}).$mount('#quickQuoteApp')
This is run on a page where #quickQuoteApp contains a <router-view> element. Users get to this page by navigating to (on local machine) localhost/QuickQuote/QuickQuoteRefactor. The components load and I see the hash get added to the end of the url for a split second (localhost/QuickQuote/QuickQuoteRefactor#) before it changes to localhost/#/ for some reason.
Any ideas on why this is happening. I thought the 'base' option was supposed to take care of this.
I discovered that this was caused by a conflict between vue-router and jquery.history.js
Not sure of the exact cause but it looked like History was trying to 'correct' the hash changes in the url made by vue-router, therefore breaking it.