Angular - How can I activate AUX route with lazy loaded module? - javascript

I have an angular app which is loading lazily module.
At first the app is navigating to home where it loads the module ( named module1) :
main routing :
const routes: Routes = [
{ path: "", redirectTo: "/home", pathMatch: "full" },
{ path: "home", loadChildren: "./module1/module1.module#Module1Module" },
];
At module1 - there's also routing table :
const routes: Routes = [
{
path: "", component: Home1Component,
children: [
{ path: 'bird', outlet: 'under', component: Home2Component }
]
}
];
So since it's loading lazily , when the app starts - it goes to /home where there it loads the Home1Component
But Home1Component also has a button in it which suppose to set a value to the outlet route .
home1.component.html:
<input value="click to activate aux route" type="button" (click)="go()"/>
<router-outlet ></router-outlet>
<router-outlet name='under'></router-outlet> //<---- I want to activate only this
This is how I try to activate the outlet route :
public go() {
this.router.navigate([{ outlets: { under: ['bird'] } }], { relativeTo: this.route })
}
But I get an error :
Error: Cannot match any routes. URL Segment: 'home'
Question :
Why am I getting this error and how can I fix it ?
Online code here : Stackblitz

Well with the help of #jmw5598 who referenced me to the problem/bug with the router .
There is a problem with default empty location for lazy loaded modules.
Here is a working solution for the problem .
The key thing to understand is that lazy modules should not have empty root path
Related specific description :

Related

angular 14 default router with param

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.

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.

How can I use tabs and pages in one application?

Is it possible to use tabs with pages?
I made an example. It has the following structure:
main (page)
tabs (use as a container)
---> app-routing.module.ts (routing for tabs)
---> home (tab)
---> contacts (tab)
---> details (tab)
---> about (tab)
If I use tabs as the default route, everything works(in app-routing.module.ts).
const routes: Routes = [
// { path: '', loadChildren: './main/main.module#MainPageModule' },
{ path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
];
If I use the default route for the main page, then an error will appear when switching to tabs(in app-routing.module.ts).
const routes: Routes = [
{ path: '', loadChildren: './main/main.module#MainPageModule' },
{ path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule' },
];
core.js:9110 ERROR Error: Uncaught (in promise): Error: Cannot match
any routes. URL Segment: 'tabs/home' Error: Cannot match any routes.
URL Segment: 'tabs/home'
How can I use tabs and pages in one application?
You need to add
RouterModule.forChild([
{
path: '',
component: TabsPage
}
])
To your tabs.module.ts in the imports sections.
Otherwise the router doesn't know which page of the Tab Module to Render

Angular 7 - Another Wildcard routing not working

I got this error when debugging routing:
{ path: 'login' , component : LoginComponent },
{ path : '' , component : DashboardComponent , outlet: "main-route", pathMatch: 'full'},
{ path: '404' , component : PageNotFoundComponent , outlet: "main-route"},
{ path: '403' , component : PermissionDeniedComponent , outlet: "main-route"},
{ path: '**' , redirectTo : '404' , pathMatch: 'full'}
This is my routes.
When I try: http://server_ip/not-exist
Im expecting to go to 404 page.
However, I got this:
Router Event: NavigationStart
platform-browser.js:211 NavigationStart(id: 1, url: '/not-exist')
platform-browser.js:211 NavigationStart {id: 1, url: "/not-exist", navigationTrigger: "imperative", restoredState: null}
platform-browser.js:216 Router Event: NavigationError
platform-browser.js:211 NavigationError(id: 1, url: '/not-exist', error: Error: Cannot match any routes. URL Segment: 'not-exist')
platform-browser.js:211 NavigationError {id: 1, url: "/not-exist", error: Error: Cannot match any routes. URL Segment: 'not-exist'
at ApplyRedirects.push../node_modules/…}
core.js:15724 ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'not-exist'
Error: Cannot match any routes. URL Segment: 'not-exist'
at ApplyRedirects.push../node_modules/#angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:2469)
at CatchSubscriber.selector (router.js:2450)
at CatchSubscriber.push../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at TapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
Where im wrong?
UPDATE 2019/10/07
The Angular error is misleading. Angular needs a "non named" route. Then you can add a named outlet.
Then I have tried to trigger this outlet.
Now. Im including a sub-component with its own routes to be added to the main routes.
//app.routing
{
path: 'external-module',
loadChildren: () => import('./external-module/external-module.module').then(mod => mod.ExternalModuleModule)
},
[...]
//external module routing
const routes: Routes = [
{
path : '',
component : ExternalModuleHomeComponent,
outlet: 'sub'
},
{
path : 'second',
component : ExternalModuleSecondComponent,
},
];
//layout.html
<div style="padding: 20px 10px 10px 20px; border: 1px solid black;">
<router-outlet></router-outlet>
</div>
<div style="padding: 20px 10px 10px 20px; border: 1px solid red;">
<router-outlet name="sub"></router-outlet>
</div>
With this configuration, when I click on this button:
<button routerLink="/external-module">home</button>
ExternalModuleHomeComponent is correctly loaded in "sub" router-outlet
When I click on this button:
<button routerLink="/external-module/second">second linik</button>
ExternalModuleSecondComponent is loaded in "primary non named" router-outlet AND the ExternalModuleHomeComponent is loaded in "sub" outlet (!!!!!).
Now. I want the SecondComponent to be loaded in "sub" router as its father.
I then tried simply adding outlet as father:
{
path : 'second',
component : ExternalModuleSecondComponent,
outlet: 'sub'
},
This solution DON'T WORK. I got the famous 404 page loaded.
I then tried to move the "second" route inside the father:
{
path : '',
component : ExternalModuleHomeComponent,
children: [
{
path: 'second', component: ExternalModuleSecondComponent, outlet: 'sub'
}
]
,
outlet: 'sub'
}
Another 404, even removing outlet : "sub" in the child.
Im really tired. There is no examples on internet with a sub-app routing inclusion like this.
The wildcard route must be
{ path: '**', redirectTo : '404'} // if you like to redirect or
{path: '**', component: NotFoundComponent} // show the component
The wildcard route must be the last route among all routes whatever
application has multiple modules.
Think, you have multiple modules, and the WildcardRoutingModule has
RouterModule.forChild([
{
path: '**',
component: redirectTo : '404'
}
])
In the Root module, you should give the last position to WildcardRoutingModule
#NgModule({
imports: [
BrowserModule,
AppRoutingModule, // included Root routes
SignInModule, // included Child routes
LayoutModule, // included Child routes
AdminpanelModule, // included Child routes
WildcardRoutingModule // Since it has wildcardRouting, it should be the last Module among all other Routing module
],
.....
})
export class AppModule {
}

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