Adding :id to guarded component path causes infinite loop? - javascript

This stackblitz demo should not render because of the :id path variable in the route to the guarded HelloComponent.
{ path: ':id', component: HelloComponent, canActivate: [AuthGuard] },
{ path: '', component: CollectionPageComponent, canActivate: [AuthGuard] }];
If :id is removed, then the login view renders, since both paths will be guarded, but if the :id variable is added back to the path, the demo spins forever.
Is this a bug or am I violating some router principle by adding :id to this location?
Note that I replaced the ViewBook component with a HelloComponent just for trouble shooting purposes. The books module is lazy and the way that this is supposed to work is that if the user authenticates and selects a book in search the book can be shown with the path books/4545342, which would trigger the :id path, but if just books is requested, without a path parameter then the book collection is shown.
I'm using this demo as a reference point. Is uses a essentially the same routing configuration.
I tried flipping the path parameters here. It seems in older versions of Angular the order does not matter, but now it does.
Filed a bug report here

When using the router, you have to be careful where you import modules. Ideally, you won't import a lazy loaded module in your application anywhere.
In your case, you're importing the book module into your app module. This adds the routes to the router config at the root level. The router does fancy unknown-to-me things with lazy loaded modules. Routes that cannot be activated won't be added to the config.
See new config after removing book module from app module:
0: {path: "login", component: ƒ}
1: {path: "", redirectTo: "books", pathMatch: "full"}
2: {path: "books", loadChildren: ƒ, _loadedConfig: LoadedRouterConfig}
3: {path: "**", component: ƒ}
VS before the move:
0: {path: ":id", component: ƒ}
1: {path: "", component: ƒ}
2: {path: "login", component: ƒ}
3: {path: "", redirectTo: "books", pathMatch: "full"}
4: {path: "books", loadChildren: ƒ, _loadedConfig: LoadedRouterConfig}
5: {path: "**", component: ƒ}
To fix: simply don't import your book module in the app module. In your case, you'll need to import the HttpClientModule in your book module.

Try this, pay attention I change the order, and added pathMatch to '' route,
{ path: '', component: CollectionPageComponent, pathMatch: 'full', canActivate: [AuthGuard] },
{ path: ':id', component: HelloComponent, canActivate: [AuthGuard] },
if the issue is not solved let me know to delete my answer

Related

When are routed components initialized?

I have the following route:
path: ':id', component: ViewBookPageComponent },
And when added it produces the error:
Error: Cannot read property 'id' of null
I'm not performing a null check in the component since the property will be available when the component is navigated to and in this case the auth guard is also keeping rerouting to login prior to any of the book routes being shown.
This is a stacblitz demo:
https://stackblitz.com/edit/angular-ngrx-slice-demo-fork-with-id-route?file=src%2Fapp%2Fbooks%2Findex.ts
If I comment out the route, the error no longer appears, so it seems Angular is instantiating the component prior to it being routed to.
Is the following fix your problem?
const routes: Routes = [
{
path: 'find',
component: FindBookPageComponent,
},
children:[
{
path: 'result',
component: SearchResultComponent,
},
children:[
{
path: 'book/:id',
component: ViewBookPageComponent ,
}
]
]
]
The AuthGuard is not protecting the route. It needs to be declared within the Book module itself. See this question for more details.

Angular Routes: Problem defining a NotFoundComponent with multiple routings files

I am creating a NotFoundComponent so that every non-existing url, a friendly page will apear to the user.
My Angular 6 project has 5 features(CRUDL):
CompanyComponent,
EmployeeComponent,
BranchComponent,
BenefitsComponent,
MainComponent
Each component have it own .module and .routing, for example the company.routing.ts defines the route like this:
export const routes: Routes = [
{
path: "branch",
component: EmptyComponent,
}
...
#NgModule({
imports: [
RouterModule.forChild(routes),
...
it also defines its childrens, like path: "branch/:id".
So, i have no problem with the way i built the routing.
The problem I am facing now is the way I can define a path to the NotFoundComponent.
Because I don't have a single file where I define my routes, if I put the definition of the /404 page on the on the bottom of routers definition in the main.routing.ts, every other route defined on the features(like the company.routing.ts) will be redirected to the /404, since angular uses the first match strategy.
Things i tried so far:
on the main.routing.ts:
export const routes: Routes = [
{
path: "main",
component: MainComponent,
},
{
path: "404",
resolve: {
routeTitle: TitleResolver,
},
component: NotFoundComponent,
},
{
path: "",
pathMatch: "full",
redirectTo: "/main",
},
{
path: "**",
redirectTo: "/404",
}
if I put this way, when I try accessing the route /company (defined in the company.routing.ts) it will be redirected to the /404.
I also tried defining it on any a routing of one of my features, like on the company.routing.ts
{
path: "**",
redirectTo: "/404",
}
Than, a funny thing happened, if I define this piece of code on the benefits.routing.ts, i can access /benefits but /branch, /employee and the rest of the routes will be redirected to /404.
if I define it on branch, I can access /benefits, /branch but /employee and the rest of the routes will be redirected to /404.
I could just place this code on the last feature loaded and it would work but I would like to know if I can solve this with another approach, can't I define a route that I want to be the last one loaded?
thanks in advance.

Router not correctly loading default route on application load

I've been struggling with this issue for the past day and a half and still have made no progress. Currently, I am attempting to load my angular app and have it default to a particular page when the application is bootstrapped. Unfortunately, it redirects to a different route.
I'm trying to go to:
https://clwd0002278/ControlTower/NICK/UI/#/
When I initially load, though, it goes to https://clwd0002278/ControlTower/NICK/UI/#/ControlTower/NICK/UI/, which results in the 404 page being hit.
I'll also try to go to https://clwd0002278/ControlTower/NICK/UI/ with the same result as above.
Here's the code so someone can try to make sense of this:
const routes: Routes = [
{path: '', redirectTo: 'patients', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent},
{path: 'notifications', component: NotificationsComponent},
{path: 'patients', component: PatientListComponent},
{path: '404', component: NotFoundComponent},
{path: '**', component: NotFoundComponent},
];
#NgModule({
imports: [
RouterModule.forRoot(routes, {useHash: true})
],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Here's the base-href on the html page:
<base href="#">
I have tried changing base-href and deploy-url in the build script, as well as omitting them entirely. I'm just not sure what I'm missing at this point.
Any help would be appreciated, and just ask if you need more information.
Edit:
The application exists at https://clwd0002278/ControlTower/NICK/UI/ and NOT at https://clwd0002278/.
Add
<head>
<base href="/ControlTower/NICK/UI">
...
</head>
to your index.html
or provide int in AppModule like
import { APP_BASE_HREF } from '#angular/common';
...
providers: [{APP_BASE_HREF, useValue: '/ControlTower/NICK/UI'}]
See also
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
https://angular.io/api/common/APP_BASE_HREF
Always your default route must be at the before the path "**".
{path: '404', component: NotFoundComponent},
{path: '', redirectTo: 'patients', pathMatch: 'full'},
{path: '**', component: NotFoundComponent},
Refer
https://angular.io/guide/router
So, it turns out that there was some code from ngrx that was pulled in from our base project package that kept throwing the location.pathname onto the end of the url for the angular/ngrx routing packages. I'm so frustrated and yet so relieved to have finally resolved this issue.
I commented out the reducers and initial state related to this to solve my issue. So, be careful of how ngrx interacts with your url!

Angular2 Best practice for routing null path

I want to set the routing for null path.
While login, getting the role of the user and set the redirect url in the local storage according to the user role which I have to set as the default routing url for null path in app.routing.ts which is included as the routing file in app.module.ts.
I tried like:
export const AppRoutes: Routes = [{
path: '',
redirectTo: localStorage.getItem('redirectUrl'),
pathMatch: 'full',
canActivate: [AuthGuard]
}, {
path: '',
component: AdminLayoutComponent,
children: [
{
path: 'dashboard',
loadChildren: './dashboard/dashboard.module#DashboardModule',
canActivate: [AuthGuard]
}]
}];
But while compiling the typescript, it is showing the following error:
ERROR in Error encountered resolving symbol values statically. Calling function 'localStorage', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol AppRoutes in /var/www/SSNW/client/src/app/app.routing.ts, resolving symbol AppModule in /var/www/SSNW/client/src/app/app.module.ts, resolving symbol AppModule in /var/www/SSNW/client/src/app/app.module.ts, resolving symbol AppModule in /var/www/SSNW/client/src/app/app.module.ts
Next alternative is to create a component and specify that in the null path component.
What is the best practice to do it.

Angular 4 lazy load module doesn't work with named child outlet

I am trying to implement lazy loading for a module. This module has a bunch of child routes with a unique outlet name. This doesn't seem to work when I try to visit the routes.
This can be seems from this example that I saved: https://plnkr.co/edit/NNXAoZItM00RIIxzemts?p=preview
You can see that I have the child route set to
{ path: 'list', component: HeroListComponent, outlet: 'abc' },
in hero-routing.module.ts
and router outlet to:
<router-outlet name="abc"></router-outlet>
in hero.component.ts
I should be able to visit localhost:3000/heroes/(abc:list) when I am running it locally, but it doesn't seem to work.
Note: You can run the plunker example locally by download the zip file and running npm install then npm start.
The child routes do not seem to work with default unamed routes.
Change the lazy loaded module routes to include a redirect from default unamed route to a named route.
const routes: Routes = [
{ path: '', redirectTo: 'start', pathMatch: 'full' },
{ path: 'start', component: HeroComponent,
children: [
{ path: 'list', component: HeroListComponent, outlet: 'abc' },
{ path: ':id', component: HeroDetailComponent }
]
}
];
Finally change the navigation link for 'heroes' lazy loaded module to include the named outlet information. Be sure to specify the complete url as '/heroes/start', do not leave it to the default '/heroes'.
<a [routerLink]="['/heroes/start',{outlets: {abc:['list']}}]"
routerLinkActive="active">Heroes</a>

Categories

Resources