I have an Angular2 project built with this Angular 2 Webpack Starter but I cannot get the fallback route to work correctly. In my app.routes.ts I have:
import { Routes } from '#angular/router';
import { HomeComponent } from './home';
import { DataResolver } from './app.resolver';
export const ROUTES: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'getstarted', loadChildren: './getstarted#GetStartedModule'
},
...
{
path: 'notfound', loadChildren: './notfound#NotFoundModule'
},
{
path: '**', loadChildren: './notfound#NotFoundModule'
},
];
The not found path above works correctly but the fallback route (**) does not work correctly. Instead of showing the NotFoundModule it does not load a module at all and I get no errors. However, when I do this it redirects correctly:
...
{
path: 'notfound', loadChildren: './notfound#NotFoundModule'
},
{
path: '**', redirectTo:'/notfound', pathMatch: 'full'
},
];
I do not want to redirect though because I do not want to change the url to /notfound by redirecting. How can I make my top version work or what else can I do to make this work?
So, I just tried it and it seems that you cannot use lazy routes to set your fallback page. This should work :
export const ROUTES: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'getstarted', loadChildren: './getstarted#GetStartedModule'
},
...
{
path: 'notfound', loadChildren: './notfound#NotFoundModule'
},
{
path: '**', component : NotFoundComponent
},
];
Related
Im using angular and wanted to try lazy loading with multiples modules, and i getting this error Error: Cannot match any routes. URL Segment: 'home/users/profile'
So well i been like a few long hours trying to solve this problem but i foundno answer
APP MODULE
{
path: 'home',
component: HomeComponent,
loadChildren: () =>
import('./components/home/home.module').then((m) => m.HomeModule),
},
{
path: 'auth',
loadChildren: () =>
import('./components/auth/auth.module').then((m) => m.AuthModule),
},
{
path: '',
pathMatch: 'full',
redirectTo: 'home',
},
HOME ROUTING MODULE
{
path: 'users',
loadChildren: () =>
import('../users/users.module').then((m) => m.UsersModule),
},
USERS ROUTING MODULE
{
path: '',
outlet: 'child',
component: UsersComponent,
},
{
path: 'user/:id',
outlet: 'child',
component: UserComponent,
},
{
path: 'profile',
outlet: 'child',
component: ProfileComponent,
},
Here is the repo if you need to see something else https://github.com/ginebras/user-system
I don't see any need for using named outlets, you are complicating things for yourself. Let's keep it simple, So I removed 'child' from your <router-outlet> as well as removed outlet: child from your routes.
I updated your User's Routing in user-routing.module, It should look like this:
RouterModule.forChild([
{
path: '',
component: UsersComponent,
pathMatch: 'full',
},
{ path: 'profile', component: ProfileComponent },
{
path: 'user-detail/:id',
component: UserComponent,
},
]),
],
I also changed the user:/id path to user-detail:id for readability. You can change it back or you change from where you are opening user:/id to user-detail:id.
I update the stackblitz too, have a look: https://stackblitz.com/edit/angular-ivy-rmxi8g?
Welcome Alejø.
Most likely you need to remove this line
component: HomeComponent,
You need to use component or loadChildren but not both. You can put the HomeComponent as an empty path in the home routing module. Don't forget pathMatch: 'full' on all your empty paths.
I have my application set up where many of my components are protected. However, the user is still able to access the main page "/". I was wondering if it would be possible to redirect the user to /login if they are not authenticated without making ALL of my components children of whatever component I have on "/". I'll include a modified version of what I have below:
const routes: Routes = [
{
path: "login",
component: LoginComponent
},
{
path: "test",
component: TestComponent
},
{
path: "protected",
canActivate: [AuthGuardService],
component: ProtectedComponent
},
{
path: "alsoprotected/:id",
component: AlsoProtectedComponent,
canActivate: [AuthGuardService],
children: [
{ path: "child1", component: ChildOneComponent},
{ path: "child2", component: ChildTwoComponent},
{ path: "child3", component: ChildThreeComponent },
{ path: "child4", component: ChildFourComponent },
{ path: "child5", component: ChildFiveComponent },
{ path: "child6", component: ChildSixComponent },
{ path: "child7", component: ChildSevenComponent }
]
},
{
path: "protectedsettings",
canActivate: [AuthGuardService],
component: SettingsComponent
}
];
Is there some way to add my GuardService to my app-root component?
You can create a componentless route in the same level as login and move everything other than login inside that route. Then add the guard to that route.
const routes: Routes = [
{
path: "login",
component: LoginComponent
},
{
path: "",
canActivate: [AuthGuardService],
children: [
{
path: "test",
component: TestComponent
},
{
path: "protected",
canActivate: [AuthGuardService],
component: ProtectedComponent
},
{
path: "alsoprotected/:id",
component: AlsoProtectedComponent,
canActivate: [AuthGuardService],
children: [
{path: "child1", component: ChildOneComponent},
{path: "child2", component: ChildTwoComponent},
{path: "child3", component: ChildThreeComponent},
{path: "child4", component: ChildFourComponent},
{path: "child5", component: ChildFiveComponent},
{path: "child6", component: ChildSixComponent},
{path: "child7", component: ChildSevenComponent}
]
},
{
path: "protectedsettings",
canActivate: [AuthGuardService],
component: SettingsComponent
}
]
}
];
check this link for more info
Inside your app root component in the constructor you could use the router to catch the instance NavigationStart from the router.
export class AppComponent {
constructor(private router: Router) {
router.events.subscribe( (event: Event) => {
if (event instanceof NavigationStart) {
//Check either LocalStorage or cookies for value
if(!localStorage.GetItem('hasLoaded')){
this.router.navigate['./login']
}
}
});
}
}
Another option is a CanDeactiveRoute in your routing file
import { Injectable } from '#angular/core';
import { CanDeactivate } from '#angular/router';
import { Observable } from 'rxjs';
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
#Injectable()
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
Using this check alongside localStorage is a good start, you could use something like server side sessions and a HTTP Interceptor alongside this also.
Be advised the user can disable this and it's not meant to obscure or hide sensitive data. Do that on a server using secure transmission mechanisms, you've been warned.
I was trying to navigate from a parent component (Core) using an url dynamically emitted from a child component (Menubar).
The problem is that the navigation is cancelled without any reason.
To find out if the problem came from the parent component, I implemented a button in the parent component navigating to a static url, and it worked!
Core template:
<app-menubar (onNavigation)="onMenubarNavigation($event)"></app-menubar>
<button type="button" (click)="navigate()">Navigate</button>
<router-outlet><router-outlet>
Core component:
onMenubarNavigation(urlSegments: string[]): void {
this.router.navigate(urlSegments);
}
navigate(): void {
let segments: string[];
segments = ['index', 'messages'];
this.router.navigate(segments);
}
Menubar template:
<a (click)="changeRoute(element.module.route)">
// element.module route is the string: "/messages"
Menubar component:
#Output() onNavigation = new EventEmitter<string[]>();
changeRoute(url: string): void {
let urlSegments: string[];
urlSegments = url.split('/');
urlSegments[0] = 'index';
this.onNavigation.emit(urlSegments);
}
App routing module:
const routes: Routes = [
{ path: 'login', loadChildren: '.\/auth\/auth.module#AuthModule' },
{ path: 'logout', loadChildren: '.\/auth\/auth.module#AuthModule' },
{ path: '', loadChildren: './theme/core/app.core.module#AppCoreModule', pathMatch: 'full' },
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
Core routing module:
const coreRoutes: Routes = [
{
path: '',
component: AppCoreComponent,
canActivate: [AuthGuard],
children: [
{
path: 'home',
loadChildren: '..\/home\/app.home.module#AppHomeModule'
},
{
path: 'index',
loadChildren: '..\/index\/app.index.module#AppIndexModule'
},
{
path: '',
redirectTo: 'index',
pathMatch: 'full'
}
]
}
];
#NgModule({
imports: [
RouterModule.forChild(coreRoutes)
],
exports: [
RouterModule
]
})
export class AppCoreRoutingModule {}
The angular routing debug shows that both urls are the same during navigation, using the one emitted by the child component or the static one, but when I navigate using the one emitted, the navigation is cancelled and I have no idea why...
Has someone ever encoutered this kind of trouble with the angular router?
I have and Angular2 app using this Angular2 Webpack Starter. I just added a fallback route to my app.routes.ts file after adding its module (NotFoundModule) to app.module.ts and everything works great except now my home path('') does not register anymore and the NotFoundComponent loads. The code is below:
import { Routes } from '#angular/router';
import { HomeComponent } from './home';
import { NotFoundComponent } from './notfound/notfound.component';
import { DataResolver } from './app.resolver';
export const ROUTES: Routes = [
{
path: '', component: HomeComponent },
{
path: 'getstarted', loadChildren: './getstarted#GetStartedModule'
},
{
path: 'open-account', loadChildren: './open-account/#OpenAccountModule'
},
...
...
...
{
path: '**', component: NotFoundComponent
},
];
How can I fix this problem so my Home route will work properly again and the NotFoundComponent won't load in its place?
When you have routes that use '' for their path and don't have children, you'll want to specify pathMatch: 'full' for that route.
export const ROUTES: Routes = [
{
path: '', pathMatch: 'full', component: HomeComponent },
{
path: 'getstarted', loadChildren: './getstarted#GetStartedModule'
},
{
path: 'open-account', loadChildren: './open-account/#OpenAccountModule'
},
...
...
...
{
path: '**', component: NotFoundComponent
},
];
See https://angular.io/docs/js/latest/api/router/index/Routes-type-alias.html#!#matching-strategy for the reasoning.
I'm using Angular 2 routing for my application and it works pretty well but I have no idea how to define the "otherwise" route. So a route that will be displayed if none if the current URL does not correspond to any "supported" route.
Here is an example of my current configuration:
#RouteConfig([
{ path: '/', name: 'Home', component: StoryComponent, useAsDefault: true },
{ path: '/story', name: 'Story', component: StoryComponent },
{ path: '/subscription', name: 'Subscription', component: SubscriptionComponent}
])
This hasn't currently been implemented in angular 2. The best current solution is to use a solution like #Gary showed.
{ path: '**', component: PageNotFoundComponent }
as shown in the angular guide routing section(https://angular.io/docs/ts/latest/guide/router.html).
There is no 'otherwise' route in angular 2 yet. But the same functionality can be achieved using wildcard parameter, like so:
#RouteConfig([
{ path: '/', redirectTo: ['Home'] },
{ path: '/home', name: 'Home', component: HomeComponent },
// all other routes and finally at the last add
{path: '/*path', component: NotFound}
This will only load the 'NotFound' component and the url will be same as what you navigate to. In case you want all not matching routes to redirect to a '404' url, you can do something like:
//at the end of the route definitions
{ path: '/404', name: '404', component: PageNotFoundComponent },
{ path: '/*path', redirectTo:['404'] }`
Try this instead of otherwise. It works for me, not sure but seems like work in progress.
#RouteConfig([
{ path: '/**', redirectTo: ['MycmpnameCmp'] },
...
}
])
https://github.com/angular/angular/issues/4055
This worked for me:
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
// all other routes
{ path: '**', redirectTo: '/home' }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Try this
RouterModule.forRoot([
{ path: 'login', component: LoginComponent },
{ path: 'edit-event', component: EventComponent },
{ path: 'participants', component: ParticipantsComponent },
{ path: 'notification', component: NotificationComponent },
{ path: '', component: WelcomeComponent }, //default
{ path: '**', component: WelcomeComponent } //page not found route
], { useHash: true })
useHash parameter is for using hash url style
https://angular.io/docs/ts/latest/guide/router.html#!#route-config