I have an app component an its use router-outlet, and a main component (what is loaded at router-outlet)
Now I would like to place packages in that component where we can insert widgets.
App component:
<cover></cover>
<div fxFlexFill fxLayout="row" fxLayoutAlign="stretch">
<div fxFlex>
<router-outlet></router-outlet>
</div>
</div>
Main component:
<app-header></app-header>
<main-widget></main-widget> //place where I would like to load custom content
<left-widget></left-widget> //place where I would like to load custom content
<right-widget></right-widget> //place where I would like to load custom content
Main component is come from a coreModul(share module) - this is a framework we have no access to it on project level.
So I would like to put content into widgets, but have no idea how to do that.
The hard thing to me is how to pass a component into a router-outlet and show it in right place. Its possible to use ng-templates in this case?
EDIT:
App routing:
import { RouterModule, Routes } from '#angular/router';
import {
LoginComponent,
LoginGuard,
MainComponent,
} from './../_system';
import { USERS_ROUTES, UsersComponent } from './../users';
const APP_ROUTES: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', component:MainComponent, canActivate: [LoginGuard], children: [
{ path: 'users', children: USERS_ROUTES},
{ path: '', redirectTo: '/login', pathMatch: 'full'},
{ path: '**', redirectTo: '/questions'}
]}
];
export const AppRoutingModule = RouterModule.forRoot(APP_ROUTES);
Related
My root component is loading twice even though I have a separate component for my homepage. I have tried to use different things, such as pathMatch, separate component, etc, but no luck. When I go to /dashboard, it works just fine, but when it loads the page initially (root page), the navbar is loaded twice. I want to avoid that.+
My code looks like this:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { NavbarComponent } from './navbar/navbar.component';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { RouterModule, Routes } from '#angular/router';
import { RootComponent } from './root/root.component';
import { FeatureDashboardComponent } from '#angular/dashboard';
import { FeatureHomepageComponent } from '#angular/homepage';
const routes: Routes = [
{
path: '',
component: RootComponent,
pathMatch: 'full',
children: [
{
path: '',
component: FeatureHomepageComponent
}
]
},
{
path: 'dashboard',
component: FeatureDashboardComponent
},
{
path: '**',
redirectTo: ''
}
];
#NgModule({
declarations: [
NavbarComponent,
RootComponent
],
imports: [
BrowserModule,
NgbModule,
RouterModule.forRoot(routes)],
providers: [],
bootstrap: [RootComponent],
})
export class AppModule {}
And my HTML for RootComponent is:
<angular-navbar></angular-navbar>
<div class="layout">
<router-outlet></router-outlet>
</div>
And navbar is:
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand">My App</a>
</div>
</nav>
Example in inspect
I think the problem might be that you have the route '' loading the RootComponent and the children route tries to load FeatureHomepageComponent but is also '', which can't be effectively resolved by the router.
Try giving the children route a path that is not empty, like this:
...
{
path: '',
component: RootComponent,
pathMatch: 'full',
children: [
{
path: 'home',
component: FeatureHomepageComponent
}
]
},
...
And play with the redirect at the end, so when your application loads, it should navigate to (for example) localhost:4200/home
I think the problem is with this code:
path: '',
component: RootComponent,
you most likely do NOT want to have your RootComponent here as it would allow the RootComponent to appear within your
<router-outlet>
and could explain why you have 2 of them.
<router-outlet>
should only route to CHILDREN of your RootComponent.
In other words, no route (in your routing config) should render your RootComponent it's already being rendered. The routes there should only render what you want to display WITHIN your router-outlet, aka CHILDREN of your RootComponent
For the solution I think you just have to make this:
path: '',
component: FeatureHomepageComponent
the first path in your config (delete the RootComponet part and the children:[] part)
Instead of calling the router-outlet try to call to the exact component name
This means you have either of two: another <router-outlet></router-outlet> instance or you are instantiating the <angular-navbar></angular-navbar> in another template other than the one you show here. pathMatch has nothing to do here because the <angular-navbar></angular-navbar> component is route agnostic, meaning it is a layout component.
i have a question.
I have 2 router outlets in my angular app.
First one is in app.component.html and is loaded for regular users and site visitors. The router works fine and all components in it are being perfectly loaded
<ng-container *ngIf="!isAdmin">
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
</ng-container>
Here is the appRoutingModule, which is forRoot
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { HomeComponent } from './home/home.component';
import { CatalogComponent } from './movies/catalog/catalog.component';
import { NotFoundComponent } from './not-found/not-found.component';
import { AuthActivate } from './core/guards/auth.activate';
import { AboutComponent } from './about/about.component';
import { ReqComponent } from './req/req.component';
const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: '/home'
},
{
path: 'home',
component: HomeComponent,
},
{
path: 'about',
component: AboutComponent
},
{
path: 'catalog',
component: CatalogComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: true,
authenticationFailureRedirectUrl: '/',
}
},
{
path: 'req',
component: ReqComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: true,
authenticationFailureRedirectUrl: '/',
}
},
// all others
{
path: '**',
component: NotFoundComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes, {enableTracing: true})],
exports: [RouterModule]
})
export class AppRoutingModule { }
I have a second route outlet for admin users only. If user that logs is admin, the dashboard is being showed. It loads entirerly different css, header and footer. The outlet has its own routing, which works.
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AuthActivate } from '../core/guards/auth.activate';
import { UserslistComponent } from './userslist/userslist.component';
const routes: Routes = [
{
path: 'admin-home',
component: UserslistComponent,
canActivate: [AuthActivate],
outlet: 'admin',
data: {
authenticationRequired: true,
admin: true,
authenticationFailureRedirectUrl: '/about',
}
},
{
path: 'userlist',
component: UserslistComponent,
canActivate: [AuthActivate],
outlet: 'admin',
data: {
authenticationRequired: true,
admin: true,
authenticationFailureRedirectUrl: '/about',
}
},
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminRoutingModule { }
the outlet in app.component.html
<ng-container *ngIf="isAdmin">
<app-adminheader></app-adminheader>
<router-outlet name="admin"></router-outlet>
<app-adminfooter></app-adminfooter>
</ng-container>
So both outlets work fine for different users. Header and footer depending on user permissions are loaded and displayed correctly.
But if i want to render HTML in the page body in between header and footer for admin, for example as the root displays, under 'userlist' load UserListComponent. the html of this userListComponent is not being displayed
I tried with 5 newly created components.
Is there any explanation on this?
Thank you for your time :)
And if checked in DOM, we see that the router-outlet is shown, but it is empty
schreenshot shows empty dom, white space, where the component userslistcomponent should be rendered and on the left side - part of the adminheadercomponent, which displays correctly
How do you access the "admin" routes?
With that implementation the URL that should show the proper admin component should look like this:
'/home/(admin:admin-home)'
are you doing that?
I'm not sure if you get the idea of secondary routes correctly :) - secondary routes (so the ones with outlet) are kind of like a child to the main route - I mean that in one time we can use two router-outlets.
In your case there are just two different route trees - one for regular users and one for admin. Therefore you shouldn't use secondary routing, but instead design the architecture like this:
<ng-container *ngIf="admin">
<app-admin-header></app-admin-header>
<router-outlet></router-outlet>
<app-admin-footer></app-admin-footer>
</ng-container>
<ng-container *ngIf="!admin">
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
</ng-container>
and the routes config:
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
},
{
path: 'admin-home',
component: AdminHomeComponent,
},
...
]
Then you can access regular home by resolving route /home/ and admin home with /admin-home/. These two routes are on the same level - think about them as two separate ways to go :)
Thanks for the answer
Hi answering your question, i do access admin routes like this
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
},
{
path: 'admin-home',
component: AdminHomeComponent,
outlet: "admin"
},
...
]
. with outlet: "admin" i enter the admin router outlet. I use different modules for different paths. For example, for user i have this routing module
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AuthActivate } from '../core/guards/auth.activate';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { RegisterComponent } from './register/register.component';
import { EditProfileComponent } from './edit-profile/edit-profile.component';
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: false,
authenticationFailureRedirectUrl: '/',
}
},
{
path: 'register',
component: RegisterComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: false,
authenticationFailureRedirectUrl: '/',
}
},
{
path: 'profile',
component: ProfileComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: true,
authenticationFailureRedirectUrl: '/login',
}
},
{
path: 'edit-profile',
component: EditProfileComponent,
canActivate: [AuthActivate],
data: {
authenticationRequired: true,
authenticationFailureRedirectUrl: '/',
}
},
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class UserRoutingModule { }
Meaning i do separate the routes specific for the user in this module. This works. I did separate the routes for the admin as well for user and quest and i decided to use another outlet for admins only, this is when i realised html is no longer rendered for the components, represented by this new outlet. the components i render with
user-routing.module.ts
guest-routing.module.ts
work fine, but they get the routes from the main outlet
I will try to use the main outlet for the admin routes as well, as you proposed , will see thanks :)
I have a problem with my angular 8 app, not rendering into a named router-outlet.
The routes are:
routes.module:
const routes: Routes = [
...
{
path: 'settings', loadChildren: './settings/settings.module#SettingsModule', canActivate
},
]
settings.module
RouterModule.forChild([
{
path: '', component: SettingsComponent
},
{
path: 'profile', component: ProfileComponent, outlet: 'settings_o'
},
{
path: 'users', component: UsersComponent, outlet: 'settings_o'
}
])
settings.component.html
<nav mat-tab-nav-bar color="primary" class="bg-whitesmoke primary">
<span mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="[{outlets: {settings_o: [link.link]}}]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</span>
</nav>
<router-outlet name="settings_o"></router-outlet>
When I click a link, the url in the address bar changes (e.g. to http://localhost:4200/settings/(settings_o:profile)), but no content is rendered to settings_o, nor do the components get loaded. There is no error in the console.
link.link is, for example simply profile like in settings.module's routes.
What do I need to change?
This is a known bug which has been discussed a lot: https://github.com/angular/angular/issues/10981
As far as I know it hasn't been solved completely but there are workarounds: https://github.com/angular/angular/issues/10981#issuecomment-454425220
You should give the lazy loaded module a default route and define the child routes for the components that you would like to open in the named outlet, for example:
RouterModule.forChild([
{
path: "default",
component: SettingsComponent,
children: [
{ path: "profile", component: ProfileComponent,outlet: "settings_o" },
{ path: "users", component: UsersComponent, outlet: "settings_o" }
]
}
]);
Of course you have to change the navigation to the SettingsComponent accordingly: routerLink='/settings/default'
I made a Stackblitz which is not an exact copy of your code but which shows how it can be solved: https://stackblitz.com/edit/angular-nctjpv
By the way, in your original solution, if you placed the named router outlet in the root component, I think it would display the child component but in the wrong place.
I am a beginner of Angular2. When I am learning angular2 routing service from https://angular.io/tutorial/toh-pt5. I want to have herocomponent always displayed so I in the app.component.html like this:
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/heroes">Heroes</a>
<a routerLink="/dummy">Dummy</a>
</nav>
<app-heroes></app-heroes>
<router-outlet></router-outlet>
<app-messages></app-messages>
And here is the app-routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HeroesComponent } from './heroes/heroes.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import {DummyComponentComponent} from './dummy-component/dummy-component.component';
const routes: Routes = [
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: 'heroes', component: HeroesComponent },
{path: 'dummy',component:DummyComponentComponent}
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
Strangely, when I click a hero on /dashboard or /heroes page it can direct to the correct URL and show the correct hero detail.
However, when I am on /detail/{{hero.id}} and click the hero on the hero component it can redirect the URL but the content in doesn't update. Can someone please help me with this?
if below is not issue then it should be issue that you are just changing parameter url that is reason its not updating
//put this code in your hero.component.ts file
ngOnInit() {
this.route.params.subscribe((params) => {
this.id = +params['id'];
this.loadComponentAgain();
});
}
above code monitor change in param value and update your component according to it.
There is issue because of this html
<app-heroes></app-heroes>
<router-outlet></router-outlet>
you are loading app-heroes component out side router-outlet, it should be loaded under router-outlet, so you should do this
<!-- <app-heroes></app-heroes> remove this-->
<router-outlet></router-outlet>
For changing a route with dynamic value you need to set your routerLink like this
[routerLink]="['/detail',hero.id]"
I have define 2 Routes LoginComponent and DashboardComponent and their is one main component which is the base component appComponent (which i have not used)
What I want is:
First Load the LoginComponent and then I Login Successfully then I want to Load the DashboardComponent.
What I have done is:
I have make the base component to the loginComponent as a selector in index.html page and when I successfully login the the LoginComponent View not Removed and Replace to Dashboard Page.
Here is my Code:
Routes:
const appRoutes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: '', redirectTo: '/login',pathMatch:'full' },
{ path: '**', component: NotFound404Component }
];
Used this for login function:
this.router.navigate(['/dashboard']);
Any help would appriciated.