angular 14 default router with param - javascript

I created an angular app with the last version, i updated the base href to /popup to have the url http://localhost:4200/popup
i want, when the application opens in the url http://localhost:4200/popup, it redirects me to a 404 page, but when i add a param in the url http://localhost:4200/popup/444444444 is opens a specific page.
I tried with the below code but i have this error:
main.ts:13 Error: NG04014: Invalid configuration of route
'/:requestNumber': path cannot start with a slash
<base href="/popup" />
export const routes: Routes = [
{ path: '', redirectTo: '/:requestNumber', pathMatch: 'full' },
{
path: '/:requestNumber',
component: AppComponent,
resolve: { payment: PaymentResolverService },
},
];
I added the resolver to check if the url has a param requestNumber or not.

The question isn't clear. If I understood you right - you can't expect a route with /popup/444444 to be caught by an empty path (because it is not an empty path, because it has 44444 in it), therefore, you can't write this:
{ path: '', redirectTo: '/:requestNumber', pathMatch: 'full' }
The path configuration above picks up empty paths, i.e. /popup/, when you want it to redirect to /popup/:requestNumber, where will it get the request number from?? (remember, the path that got you here was /popup/)
You can write this though, where empty paths are redirected to a 404 page:
export const routes: Routes = [
{
path: '',
component: Some404Page,
},
{
path: ':requestNumber',
redirectTo: 'popup/:requestNumber',
pathMatch: 'full',
},
{
path: 'popup/:requestNumber',
component: AppComponent,
resolve: { payment: PaymentResolverService },
},
];

Since this is the only hit on Google, I'll just add a side-answer.
I was getting this error for apparently this route:
{
path: 'stuff/moduleA',
loadChildren: () => import('./modules/module-a/module-a.module').then(m => m.module-a)
},
Which didn't make sense since there's clearly no leading slash there. The problem was actually that this lazily loaded module contained a route that looked like this:
{
path: '/',
component: AComponent,
},
The fix was to change this path by changing it to path: ''.
So check the routes inside of the loaded module, even if that route isn't mentioned in the error.

Related

How to fully reload an Angular component only when user is logged in?

In my Angular project I've got:
SignInComponent -> Handling the login requests
DashboardComponent -> Displayed for all children when user has successfully logged in
HomeComponent -> The actual content/page that will be displayed to the user - A child of 'DashboardComponent'
And it looks like:
export const appRoutes: Routes = [
{
path: 'login', component: SignInComponent
},
{
path: '', component: DashboardComponent,
children: [
{ path: '', component: HomeComponent },
],
canActivate: [AuthGuard]
},
{
path: '', redirectTo: '/login', pathMatch: 'prefix'
}
]
Now the problem that I'm facing, is that when the user is successfully logged in, that it won't reload the component 'DashboardComponent'. And I'm not referring to the routes itself (those are going fine). But there's one needed JS script not loaded which blocks the user from expanding the menu item(s). See below:
However, when you manually reload the page, it will work. The menu item(s) will expand. See below:
So, fully reloading the component would do the trick, but I only want that when it's matching with the previous 'route', in this case '/login'. In other words, I would to fully reload the 'DashboardComponent', only when it's not a 'child'. How could I apply this?
Or is there perhaps a better and easier approach?
Here it looks some url match problem because you have defined path:'' to dashboard also making that path to redirect to login with next routing object in routes array
export const appRoutes: Routes = [
{
path: 'login', component: SignInComponent
},
{
path: 'dashboard', component: DashboardComponent,
children: [
{ path: 'home', component: HomeComponent },
],
canActivate: [AuthGuard]
},
{
path: '', redirectTo: '/login', pathMatch: 'prefix'
}
]
So change it like above code and try. This will not make any url confusion and redirection will take place properly
Update:
It seems that custom code (JS) is being called on document ready event. That explains why it's working the only first time. See comment: https://stackoverflow.com/a/46349639/2318669.
What I've done to solve it:
I declared a variable:
declare const openMobileMenu: any;
And then I bind it from the component:
onMobile() {
openMobileMenu();
}
To the following method in the JS file:
function openMobileMenu() {
$(".horizontal-menu .bottom-navbar").toggleClass("header-toggled");
};
Thanks anyway for the support! :)
I appreciate it.

Angular 6 conflict in router links on same root

i have two routes :-
1- http://localhost:4200/members/10 ===> this for member's page
2- http://localhost:4200/members/10?tab=3 ===> this for chat page
I want to make chat as a paid service so I create component I called it charge with this route ==> http://localhost:4200/charge so if any member like to go to chat route he will be redirected to charge page as I create code in ngOnInit method in chat component like that
if(!this.authService.paid)
{this.router.navigate(['charge']);}
When I go chat it redirects me to charge page and that's cool , the problem is that when I go member'page it redirects me to charge page and that's not cool at all, so please help me what can i do to solve this problem, thanks in advance
and this is my routes
export const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{
path: '',
runGuardsAndResolvers: 'always'
, canActivate: [AuthGuard],
children: [
{
path: 'members', component: MemberListComponent, resolve: {
users: MemberListResolver
}
},
{
path: 'member/edit', component: MemberEditComponent, resolve: {
user: MemberEditResolver
}, canDeactivate: [PreventUnsavedChangesGuard]
},
{
path: 'members/:id', component: MemberDetailComponent, resolve: {
user: MemberDetailResolver
}
},
{
path: 'lists', component: ListsComponent, resolve: {
users: ListResolver
}
},
{ path: 'messages', component: MessagesComponent, resolve: { messages: MessageResolver }, canActivate: [MessagesGuard] },
{ path: 'charge', component: PaymentComponent }
]
},
{ path: '**', redirectTo: '', pathMatch: 'full' }
];
It looks like you use the same ngOnInit implementation for both pages '/member' and '/chat'. And if this !this.authService.payed returns true, you will always be redirected to '/charge' page.
But to have a better understanding, please provide your routing configuration.
Edit:
Thank you for adding your routes.
{
path: 'members/:id', component: MemberDetailComponent, resolve: {
user: MemberDetailResolver
}
}
It seems like you check for !this.authService.payed in MemberDetailComponent#ngOnInit, but you probably do not check your queryParam ?tab=3.
To fix this issue quickly you can modify your if-condition:
if(!this.authService.payed && this.route.snapshot.queryParams['tab'] === 3)
where this.route has to be injected via constructor parameter
constructor(private route: ActivatedRoute)
But
I think the best solution for this issue would be to add another child route for chat page and handle authorization with another 'canActivate'.

Angular lazy loading - don't see it is working

I defined a lazy loading module.
this is SettingsRoutingModule module-
const routes: Routes = [
{
path: '',
component: SettingsStandaloneComponent,
children: [
{
path: '',
redirectTo: 'profile',
pathMatch: 'full'
},
{
path: 'profile',
component: SettingsProfileComponent
},
{
path: 'about',
component: SettingsAboutComponent
},
{
path: 'affiliations',
component: SettingsAffiliationsComponent
},
{
path: 'communication',
component: SettingsCommunicationComponent
},
{
path: 'notifications',
component: SettingsNotificationsComponent
},
{
path: 'proxies',
component: SettingsProxiesComponent
},
{
path: '**',
redirectTo: 'profile',
pathMatch: 'full'
}
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SettingsRoutingModule { }
in the AppRoutingModule module-
{ path: 'settings',
loadChildren: './settings/settings.module#SettingsModule',
canActivate: [AuthGuard],
},
in the prod production when a go to the network I don't see the "chunk.js" that everybody say that should appear". only two files that looks like- 0.34016a93d44e785b623a.js
In my localhost I see only "settings-settings-module.js"
Is it OK or does it mean that my module isn't lazy?
Because of this option "namedChunks": false in your angular.json, you won't see the named chunks anymore, instead it displays hashed-value as the file name. This is due to recent improvements(not sure from when) in angular/cli.
Yes it is OK, We do not see chunk.js anymore. A lazy loaded module appears with its name in network tab as mentioned by you and it appears only once for the first time. To see it again, clear everything out by clicking the circle with a line through it in the upper left of the Network Tab:
Make sure you're not filtering anything in Chrome Debugging tools in Network tab, it was driving me insane for a moment, I had everything set up perfectly.
Proof (I had 'fa' being filtered, that's why I couldn't see )
After

Angular : Lazy load multiple Modules with the same route

I have an app where i want to lazy load two modules in the same moment with the same route path.
My routing module would look like this :
{
path: 'mypath',
loadChildren: () => HomeModule,
canLoad: [HomeGuard]
},
{
path: 'mypath',
loadChildren: () => AdvisorModule,
canLoad: [AdvisorGuard]
},
but this lead to load only the first one
i cant' find anyway to do it like this for example :
{
path: 'mypath',
loadChildren: () => HomeModule, advisor module // ??
canLoad: [// ??]
},
I don't want also to import one of them in the other , as like this , only one module would be lazy loaded and the other automatically
How may it do it ??
You could rework things like this:
const routes: Routes = [
{
path: 'mypath/home',
loadChildren: () => HomeModule,
canLoad: [HomeGuard]
},
{
path: 'mypath/advisor',
loadChildren: () => AdvisorModule,
canLoad: [AdvisorGuard]
},
]
In other words move the route path to your module outside to the parent module, in this case I assume those are 'adviser' and 'home'
And then just start in the module routing with a redirect solution and/or a path like so:
Home module routing:
const routes: Routes = [
{
path: '', // <-- in your current solution probably 'home'
component: HomeParentComponent,
children: [
{ path: '', redirectTo: 'childOne', pathMatch: 'full' },
{ path: 'childOne', component: HomeChildComponentOne },
],
},
];
Advisor module routing:
const routes: Routes = [
{
path: '', // <-- in your current solution probably 'advisor'
component: AdvisorParentComponent,
children: [
{ path: '', redirectTo: 'childOne', pathMatch: 'full' },
{ path: 'childOne', component: AdvisorChildComponentOne },
],
},
];
This works nicely, you should be able to navigate to:
'/mypath/home' and end up inside your HomeParentComponent with router outlet of HomeChildComponent one.
'/mypath/advisor' and end up inside your AdvisorParentComponent with router outlet of AdvisorChildComponent one.
In case you don't want a child component inside your router outlet it is even simpler, you can just remove the child routes and redirect.
Note: If this solution doesn't resolve your issue, then please share more details on your module routing so I can get a better picture of your desired route configuration.
You need to re-arrange your routes by one level and you also need to add auxiliary routes for the extra components you want to load.
This works with Angular 9 (probably with 8 too)
{
path: 'home',
component: HostingComponentWithOutlets,
children: [
{
path: 'featureOne',
loadChildren: () => import('xxxxx').then(m => m.FeatureOneModule),
canLoad: [featureOneGuard]
},
{
path: 'featureTwo',
outlet: 'outletAux1',
loadChildren: () => import('yyyyy').then(m => m.FeatureTwoModule),
canLoad: [featureTwoGuard]
},
// you can even load more components to different outlets from the same module
// and update redirectTo and routerLink accordingly
//{
// path: 'featureThree',
// outlet: 'outletAux2',
// loadChildren: () => import('yyyyy').then(m => m.featureTwoModule),
// canLoad: [featureTwoGuard]
//},
{
path: '',
redirectTo:
'/absolute/path/to/home(featureOne/path-to-featureOne-component//outletAux1:featureTwo/path-to-featureTwo-component)',
pathMatch: 'full'
}
]
},
{ path: '', redirectTo: 'home', pathMatch: 'full' }
Hitting the 'home' route will lazy load all required modules.
In your HostingComponentWithOutlets html template where you need to link to 'featureOne':
<a [routerLink]="featureOne/path-to-featureOne-component"
and if you want to go straight to the full route with the auxiliary routes from a template:
<a [routerLink]="['.', { outlets: { 'primary': ['featureOne', 'path-to-featureOne-component'], 'outletAux1': ['featureTwo', 'path-to-featureTwo-component'] } }]"
FeatureOneModule should define 'path-to-featureOne-component' and FeatureTwoModule should define 'path-to-featureTwo-component' in their equivalent route definitions.

Angular 4 redirects to root path when browser reloads

The page is currently http://localhost:4200/foo.
Case 1: If I press the browser's reload button or type the same url in the browser, the page redirects to http://localhost:4200 (root path).
I'd like the page keeps in the same url (http://localhost:4200/foo).
Case 2: If I type http://localhost:4200/foo (same url) the page redirects to http://localhost:4200 (root path).
I also would like the page keeps in the same url I've typed (http://localhost:4200/foo).
Otherwise, if the page is http://localhost:4200 and I type http://localhost:4200/foo, it works fine. I can navigate by url paths normally. The problem is only when I go to the same path.
My root path in app.module.ts is:
const rootRouting: ModuleWithProviders = RouterModule.forRoot([
{
path: 'foo',
loadChildren: './foo/foo.module#FooModule'
},
{
path: '',
loadChildren: './bar/bar.module#BarModule'
},
], { });
And my path in foo.module.ts is:
const fooRouting: ModuleWithProviders = RouterModule.forChild([
{
path: 'foo',
component: FooComponent
}
]);
OBS: This question Angular 5 - redirect page to homepage on browser refresh wants exactly the opposite of mine. Now, I don't know what is the Angular default behavior for this cases.
Edit after DiPix's correction:
My root path in app.module.ts is:
const rootRouting: ModuleWithProviders = RouterModule.forRoot([
{
path: 'foo',
loadChildren: './foo/foo.module#FooModule'
},
{
path: '',
loadChildren: './bar/bar.module#BarModule'
},
], { });
And my path in foo.module.ts is:
const fooRouting: ModuleWithProviders = RouterModule.forChild([
{
path: '',
pathMatch: 'full',
component: FooComponent
}
]);
Edit 2:
Debugging with google chrome, I've set "Preserve log".
Testing with any other site, if you are at "www.anydomain.com/path" and you reload the browser, chrome writes "Navigated to 'www.anydomain.com/path'.
Testing with my app, if I am at "http://localhost:4200/foo" and I reload the browser, chrome writes "Navigated to 'http://localhost:4200/'.
The browser navigates to root path!
You need to define some routes at the root of your application. Something like this:
const routes: Routes = [
{ path: 'foo', component: FooComponent},
{ path: '', redirectTo: '/foo', pathMatch: 'full' },
{ path: '**', component: FooComponent }
];
These routes would go where you defined your forRoot() method which from you code looks like:
const rootRouting: ModuleWithProviders = RouterModule.forRoot(routes);
You've got path 'foo' in foo.module.ts what is suspicious. As you have already declared this path in app.module.ts. The point is that if you are using lazy loading then you shouldn't import foo.module in app.module. Check your import in app.module. I bet you've import this module. And don't forget to change path to '' in foo.module.ts

Categories