Routing submenu elements Angular 2 - javascript

I have a question regarding routing submenu elements in Angular 2.
The directory of my project looks like:
-app
---login
---registration
---mainApp (this is the main body of the app, with a static content as menu, with few links)
-----subMenu1 (link to some content)
-------(some files here)
-----subMenu2 (link to some content)
-------(some files here)
-----subMenu3 (link to some content)
-------(some files here)
---app.component.ts
---app.component.html
---app.module.ts
---app.routing
---index.ts
How does it works? First view is the login and there you have two possibilities, to enter the mainApp or enter registration form. It works fine. But now I need to handle the routing between the mainApp and sub items from this mainApp. The mainApp content is just a sidemenu, which doesn't disappear. It is always on screen, only content from sidemenu elements is changing.
What is my problem:
Do I need to provide another routing file to handle the routing between the mainApp static menu elements and the dynamic content? Or am I able to do it just from this file which handles routing between the app and login, registration and mainApp?
And if I have to make another routing file, how would it look like?
My actual routing file looks like:
import { Routes, RouterModule } from '#angular/router';
import { MainAppComponent} from './mainApp/index';
import { LoginComponent } from './login/index';
import { RegistrationComponent } from './registration/index';
const appRoutes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'mainApp', component: MainAppComponent },
{ path: 'registration', component: RegistrationComponent },
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
Let's say that I provide another routing file, would it look like this?
import { Routes, RouterModule } from '#angular/router';
import { subMenu1Component } from './subMenu1/index';
import { subMenu2Component } from './subMenu2/index';
import { subMenu3Component } from './subMenu3/index';
const appRoutes: Routes = [
{ path: '', component: mainAppComponent},
{ path: 'subMenu1', component: subMenu1Component },
{ path: 'subMenu2', component: subMenu2Component },
{ path: 'subMenu3', component: subMenu3Component },
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);

I like to split my routes off into layouts. So typically I do a secure layout and a public layout. This way I can control the authentication of the website and protect data that was meant to be secure.
In order to do this I keep a file structure as shown below,
/app.module.ts
/app.routing.ts
/layouts/secure.component.ts
/layouts/secure.component.html
/layouts/public.component.ts
/layouts/public.component.html
/secure/profile.component.ts
/secure/profile.component.html
/secure/secure.routes.ts
/public/home.component.ts
/public/home.component.html
/public/public.routes.ts
Explanation
Initially we need to register all of our components and setup the routes.
Register Components
/app.module.ts
//Layouts
import { PublicComponent } from './layouts/public.component';
import { SecureComponent } from './layouts/secure.component';
import { HomeComponent } from './public/home.component';
import { ProfileComponent } from './secure/profile.component';
#NgModule({
declarations: [
AppComponent,
PublicComponent,
SecureComponent,
HomeComponent,
ProfileComponent
],
providers: [
Guard,
Auth
]
Take special notice to the Auth under providers. This is what will help us secure the secure layout.
Next we will setup the routes.
app.routing.ts
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full', },
{ path: '', component: PublicComponent, data: { title: 'Public Views' }, children: PUBLIC_ROUTES },
{ path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
];
As you can see the [Guard] is setup using the Auth provider and is a service I use to secure the secure layouts. Now that each of these routes actually have children routes we can set those routes up to control the actual navigation of our app.
It is important to understand. These routes will direct traffic to the correct layout. Then depending on the route the child routes take over. Which in your case would be your sub components.
/secure/secure.routes.ts
import { ProfileComponent } from './profile.component';
export const SECURE_ROUTES: Routes = [
{ path: '', redirectTo: 'profile', pathMatch: 'full' },
{ path: 'profile', component: ProfileComponent },
];
Remember to import your component to the routes file so it knows which class to call when the route is enabled.
For extra credit I will go ahead and throw in a service to provide auth. This will show you how to protect your routes.
guard.service.ts
import { Injectable } from '#angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
import { Auth } from './auth.service';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class Guard implements CanActivate {
constructor(protected router: Router, protected auth: Auth ) {}
canActivate() {
if (localStorage.getItem('access_token')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page
this.router.navigate(['/home']);
return false;
}
}
By storing a token in the local storage we can check to see if it exist and authenticate the user. Once they meet the criteria they gain access to the secure routes.
Let me know if you have anymore questions.

Related

Angular 11 does not load HTML from 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 :)

Lazy loading for child routes is not redirecting to child

Hi for me parent routing is working fine, but for chid routes it is not redirecting and not getting errors also
in app.routing
const routes: Routes = [
{
path: 'card',
loadChildren: './cards/cards.module#CardsModule',
canActivate: [AuthGuard]
},
{
path: 'card/:id',
loadChildren: './cards/cards.module#CardsModule',
canActivate: [AuthGuard]
}]
in card-routing:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { Cardscomponent } from './cards.component';
import { AuthGuard } from '../_services/auth.guard';
import { CardDetailsComponent } from './card-details/card-details.component';
const routes: Routes = [
{ path: '', component: Cardscomponent,
children :[
{ path: ':id', component: CardDetailsComponent}
]
}
]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CardsRoutingModule { }
localhost:4200/card is working
but localhost:4200/card/1234 is not working and not getting any error also, any help...
Check whether you have router-outlet in child component.
When the url updated but view not rendered, it usually comes down to missing router-outlet.
Learned that from developing a entire project with angular elements.
If you enable tracing, you can see all the router events are triggered successfully.

In Angular2 routing, the URL changed but the content doesn't update

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]"

Dynamic Nested router-outlet usage in Angular 4

Dynamic Nested router-outlet usage in Angular 4
I had simple Angular CLI with dynamic routing with angular.
In my application, I had 2 different page like home and about. In that Home, I want to insert more topics with dynamic contents. so I had included nested router inside the home page. while navigating nested content it's replacing with the root element. I have attached the online sample, please check that. can anyone please provide a solution for that.
online Sample
Router configurations
import { Routes } from '#angular/router';
import { AboutComponent } from './about/about.component';
import { HomeComponent } from './home/home.component';
import { HomeNestComponent } from './home/homenest/homenest.component';
export const rootRouterConfig: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'home/homenest', component: HomeNestComponent },
];
Do the following changes in Router configurations.
import { Routes } from '#angular/router';
import { AboutComponent } from './about/about.component';
import { HomeComponent } from './home/home.component';
import { HomeNestComponent } from './home/homenest/homenest.component';
export const rootRouterConfig: Routes = [
{ path: 'home', component: HomeComponent,
children:[{ path: 'homenest', component: HomeNestComponent }]
},
{ path: 'about', component: AboutComponent },
{ path: 'homenest', component: HomeNestComponent },
];
Changes in home.component.ts.
public homeNestClick(e) {
this.router.navigateByUrl('/home/homenest');
}
https://stackblitz.com/edit/angular-tf7ru3?file=src/app/home/home.component.ts

How to pass component into router-outlet

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);

Categories

Resources