Hello i just want to know how many router-outlets i can use in angular, is there any limit?
if so how many?
Here is the link to understand "multiple outlet", for anyone who is not aware of this!
https://medium.com/angular-in-depth/angular-router-series-secondary-outlets-primer-139206595e2
Thank You
there is no limit on the outlets, however every outlet corresponds to a piece of code, that will be rendered there, and it affects the url. With more code your app will be loaded longer and there are some restrictions on url length. apart from these 2 I don't think there is any limit
If you want to use multiple <router-outlet></router-outlet> you can use it. There is no limit in angular but there are some best practices of using multiple
place one in app.component.html and if you have a number of featured modules then you can use separate for each featured module.
====== app.component.html=====
<app-header></app-header>
<!-- router-outlet will emit an activate event any time a new component is being instantiated, and a deactivate event when it is being destroyed. -->
<!-- It will act as a placeholder that angular automatically fills the current route state-->
<router-outlet></router-outlet>
<app-footer></app-footer>
======= app-routing.ts =====
export const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' , canActivate : [AuthGuardService]},
{ path: 'dashboard', component: DashboardComponent, canActivate : [AuthGuardService], data: {role: 'system'}},
{ path: 'featureModule', loadChildren: './module/featureModule.module#FeatureModule', canActivate : [AuthGuardService]},
{ path: '**', component: NotFoundComponent }
];
and in FeatureModule add saparate <router-outlet> so all components in featuredModule will get rendered in FeatureModuleComponent.html.
featureModuleComponent.Html
<app-menu [sysType]="featureModule"></app-menu>
<div class="bg-mage" [ngStyle]="{'background-image': backgroundImage, 'height': customImgHeight} ">
<router-outlet></router-outlet> <!-- router outlet of featured module -->
</div>
is there any limit?
No, there is no specific limit.
Related
Routes for my Module:
const routes: Routes = [
{ path: ":level1/:level2/:level3", component: CategoriesComponent },
{ path: ":level1/:level2", component: CategoriesComponent},
{ path: ":level1", component: CategoriesComponent},
{ path: "", component: CategoriesComponent },
];
the Categories component Generates some links like so:
<a [routerLink]="['category1']" [relativeTo]="activatedRoute">My Link</a>
the ngOnInit & ngOnDestroy are called each time it navigates between those routes.
What I need is the component to stay mounted and not re-init each time.
Stackblitz link to illustrate the difference between using QueryParameters and RouteParameters: Angular example
NOTE: Dont suggest RouteReuseStrategy: that isn't the answer we are looking for. I have another angular application that doesn't reload the component between routes. And this is the official expected behaviour.
You need to dive into a RouteReuseStrategy and create your custom strategy with saving touched pages
Docs
RouteReuseStrategy allows you to tell Angular not to destroy a component, but in fact to save it for re-rendering at a later date. https://stackoverflow.com/a/41515648/15439733
I want to render 2 components (AppComponent and UserComponent) without having to render AppComponent at all times. Here's what my code looks like:
app.routing.module.ts
const routes: Routes = [
{
path: '', component: AppComponent
},
{
path: 'user', component: UserComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div>
I'm in the app component
</div>
<router-outlet></router-outlet>
Now for some reason "I'm in the app component" text is rendered 2 times as you can see in the picture:
Now when I go to route '/user' I see this:
so my question is How can I only see "I'm in the app component" text when on on '/' route and
when I'm on '/user' route only see "user works!"? Thanks a lot in advance!
AppComponent renders by default as its the root component. You would need to create another component and use that as your home component. Please check the updated stackblitz.
My answer is: Don't. Make an OtherComponent, then remove all but the <router-outlet> tag from AppComponent.html.
Treat that AppComponent as the top level that everything flows through. Angular is very opinionated, and if you do things in a way that's not standard practice, Angular will act like it's meant to.
If the two branches should really be that separate, consider having separate apps.
This is because default route '' matches both '' and 'user' paths. Try setting pathMatch: 'full' to the AppComponent and it shouldn't render on other routes:
{
path: '',
component: AppComponent
pathMatch: 'full'
}
But more of an issue here is that the default route should be a separate component and your AppComponent should be the one that holds the router-outlet.
I'm working on a project written on Angular (v8.2.8) and use router with the same version. The architecture of the routing is the following:
I have app-routing.module.ts where I have 3 entries for routes array:
Shell.childRoutes([...array of routes]),
Case.childRoutes([...array of routes]),
{ path: '**', redirectTo: '/', pathMatch: 'full' }
Shell - that is parent component for app internal pages.
Case - that is parent component for app public pages.
Method child routes do almost the same for both components:
export class Shell {
static childRoutes(routes: Routes): Route {
return {
path: 'app',
component: ShellComponent,
children: routes,
canActivate: [AuthenticationGuard],
data: { reuse: true }
};
}
}
and
export class Case {
static childRoutes(routes: Routes): Route {
return {
path: '',
component: CaseComponent,
children: routes,
data: { reuse: true }
};
}
}
App have dashboard component for Shell parent and home component for Case parent.
User loads the page at home route and markup is the following:
<app-root>
<app-case>
<router-outlet></router-outlet>
<app-home></app-home>
</app-case>
</app-root>
And after redirect to the dashboard route I expect to have the following markup:
<app-root>
<app-shell>
<router-outlet></router-outlet>
<app-dashboard></app-dashboard>
</app-shell>
</app-root>
But I receive
<app-root>
<app-case>
<router-outlet></router-outlet>
<app-dashboard></app-dashboard>
</app-case>
</app-root>
So the exact issue is in test case:
User is on a route which exist in Shell parent.
Then if user will be redirected to any route in Case parent - the parent will stays the Shell. And the same situation works in other direction. If Case route was load first, after redirect to Shell route parent will stay the case.
I tried to edit different parameters in the childRoutes method, but no success, I just don't understand is it the issue in the engine, or I just need to specify some additional parameters.
Basically I resolved this issue. For those who had the same issue - for me issue was in custom route reusable strategy which was implemented. When I was switching from Case to Shell route-reusable-strategy function shouldReuseRoute returned true, so route was reused.
I'm using multiple named angular 8 router-outlet in a web app. All the routerLink seems to work as it changes the URL but components in my 2nd router-outlet are imported but not initialized nor rendered.
I made a Stackblitz available here : https://stackblitz.com/edit/ng-multiple-router-outlet?file=src/app/app.component.ts
As you can see, when you click on the sidebar, under photos you have a second navigation level by clicking on Google or Facebook but nothing is rendered.
In modules, components used in other modules and RouterModule are well exported to be accessible, I don't see what I've done wrong.
I tried to declare the routes with both forRoot and forChild methods, I put some logs, but I'm running out of clues.
Thanks for your help !
Angular router is pretty simple once you understand how nested routes works there.
Let's imagine a simple configuration:
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
children: [
{ path: 'child', component: ChildComponent }
]
}
])
How would you use router-outlet to cover all routes above?
app.component.html
\
contains
\
<router-outlet></router-outlet>
\/
renders
\
HomeComponent
home.component.html
\
contains
\
<router-outlet></router-outlet>
renders
\
ChildComponent
The main takeaway here is that router-outlet renders component depending on router context. Once it renders component a new context is created and all router-outlet's declared at this level will look at children configuration.
The same is true for named routes.
You've generated the link like:
(selection:facebook//sidebar:photos)
It means that these named routes should be at the same root level. But you defined <router-outlet name="selection"></router-outlet> at nested level inside rendered by router LibraryComponent.
Let's add this outlet at the same level as 'sidebar':
<router-outlet name="sidebar"></router-outlet>
<router-outlet name="selection"></router-outlet>
and it actually works stackblitz
Now let's come back to your attempt. If you want to render selection components inside selection.component.html then you should be using nested named routed links:
selection.component.html
[routerLink]="['.', { outlets: { selection: [routeName] } }]"
\/
relative path
The above binding will generate nested links like (sidebar:photos/(selection:facebook))
Now you need to move SelectionRoutes configuration to children property of photos path:
selection.module.ts
imports: [
CommonModule,
RouterModule, //.forChild(SelectionRoutes)
],
sidebar.routes.ts
import { SelectionRoutes } from '../selection/selection.routes';
...
export const SidebarRoutes: Route[] = [
{ path: 'photos', component: LibraryComponent, outlet: 'sidebar', children: SelectionRoutes },
Stackblitz Example
Update
In order to make facebook as a default subroute you create a route with redirectTo option like:
export const SelectionRoutes: Route[] = [
{ path: 'facebook', component: FacebookComponent, outlet: 'selection' },
{ path: 'google', component: GoogleComponent, outlet: 'selection' },
{ path: '', redirectTo: '/(sidebar:photos/(selection:facebook))', pathMatch: 'full', },
]
Stackblitz Example
I have something like:
const routes: Routes = [
{
path: ':path', component: SiteRoot, children: [
{ path: '', loadChildren: '../modules/maple/template.module#TemplateModule' }
]
}
];
I wish to use this :path url to match multiple module dynamically. each module have there own internal Route.
Is there any way I can achieve this?
I tried ViewContainerRef with ResolveComponentFactory but it does not work with module only component. Event with NgModuleFactoryLoader, Routes cannot be applied.
EDIT, to make everything clear:
What I am trying to achieve is to have different module display on same route path. For example user can see user dashboard at "home" path, and admin can see admin dashboard at "home" path as well.
This feature is defined by business logic, so, I cannot change admin dashboard to another url
I think you are trying to create your routing module incorrectly. Anyway, you should write why you need this. I'll try to answer. Every module should have it's own path, so routing module should be strict and static. If you trying it for security, use guards and hide item from menu component.
If you need URLs like this: "/username1/profile", "/username2/profile" you can simply use code like yours, or use lazy loading. create routing file for parent module:
{ path: ':username', loadChildren: '../users/user.module#UserModule' }
Than create routing file for child module:
{ path: '', loadChildren: 'UserComponent', children: [
{ path: '', redirectTo: 'profile' },
{ path: 'profile', component: ProfileComponent}
]
}
Updated By your case:
by your case you can change your HTML file. For example in app.component.html if your code is:
<div>
<router-outlet></router-outlet>
</div>
You can change it with:
<div *ngIf="isLoggedIn | async">
<admin-panel></admin-panel>
</div>
<div *ngIf="(!isLoggedIn | async)">
<router-outlet></router-outlet>
</div>