angular 2 show/hide router-outlet and redirect to html page
In Angular 2 Routes you have 'CanActivate' and 'CanActivateChild' property. This can be used for authorization before rendering the component.
You can find the usage here: https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
In your case, you do not have to remove the router-outlet.
Instead:
- Add only
<router-outlet></router-outlet>
in your app.component.html. -
Provide 2 routes
- Default route for your main component which requires authorization.
-
A separate route(/contact) for your contact component which is linked with the contact.html.
Import RouterModule in app module to add routes.
example:RouterModule.forRoot([ { path: '', canActivate: [AuthGuard] //provide the Injectable class here to authenticate. component: MainComponent }, { path: 'contact', component: ContentComponent } ])
Create an @Injectable class as a guard to authenticate the user. This will call the app service to authenticate the user and redirect to contact component if unauthorized. You can use
this.router.navigate(['contact']);
import Router from "@angular/router"- Add this new @Injectable class as the CanActivate property for your default route.
Kamran Pervaiz
Updated on June 05, 2022Comments
-
Kamran Pervaiz almost 2 years
I have created a simple application. I have AD windows authentication web api which is on different domain so I have enabled cors. I have created a spike of api and returning 401 when not authorized.
app.service.ts
authenticateUser(): Observable<any> { return this.http.get("http://localhost:36655/", { withCredentials: true }) .map(this.extractData) .catch(this.handleError); }
app.component.ts
@Component({ moduleId: module.id, selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.css'] }) export class AppComponent { constructor(appService: AppService) { appService.authenticateUser() .subscribe(response => { //do something here because its not 401 }, error => { if (error.indexOf("401") >= 0) console.log("Redirect to contact page") else { } }); } }
There are 2 things I am struggling with
- how do I hide Router-Outlet (reason is I don't want to show my main page/links)
- I can hide it using [hidden] on the main div but then how do I redirect? because
<router-outlet></router-outlet>
will be invisible
app.component.html
<div> <nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand" [routerLink]="['']">Home</a> <ul class="nav navbar-nav"> <li><a [routerLink]="['/factory']" id="factory" name="factory">Factory</a></li> <li><a [routerLink]="['/supplier']" id="supplier" name="supplier">Supplier</a></li> <li><a [routerLink]="['/businessarea']" id="businessArea" name="businessArea">Business Area</a></li> </ul> </div> </nav> <router-outlet></router-outlet> </div>
I have access all or no-access authentication that's why I dont want to show anything. Is there something like
router.navigate('../shared/contact.html')
?Edit 1:
app.component.ts
@Component({ moduleId: module.id, selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.css'] }) export class AppComponent { private isAuthenticated: boolean = false; constructor(private authService: AuthService) { this.authService.authenticateUser() .subscribe(response => { if (response.status == 200) this.isAuthenticated = true; }, error => { if (error.indexOf("401") >= 0) this.isAuthenticated = false; }); } }
authguard.ts
@Injectable() export class AuthGuard implements CanActivate { private isActive: boolean = true; constructor(private authService: AuthService, private router: Router) { } canActivate(): boolean { this.authService.authenticateUser() .subscribe(() => {}, error => { if (error.indexOf("401") >= 0) { let link = ['contactus']; this.router.navigate(link); this.isActive = false; } }); return this.isActive; } }
auth.service.ts
@Injectable() export class AuthService { constructor(private http: Http) { } authenticateUser(): Observable<any> { return this.http.get("http://localhost:5002/api/v1/authenticate", { withCredentials: true }) .map(this.extractData) .catch(this.handleError); } private extractData(response: Response) { let body = response; return body || {}; } private handleError(error: Response) { let errMsg: string; if (error instanceof Response) { errMsg = `${error.status} - ${error.statusText || ''}`; } else { errMsg = error.toString(); } return Observable.throw(errMsg); } }
app.component.html
<div> <nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand" [routerLink]="['']">Ethos</a> <ul class="nav navbar-nav" *ngIf="isAuthenticated"> <li><a [routerLink]="['/factory']" id="factory" name="factory">Factory</a></li> <li><a [routerLink]="['/supplier']" id="supplier" name="supplier">Supplier</a></li> <li><a [routerLink]="['/businessarea']" id="businessArea" name="businessArea">Business Area</a></li> </ul> </div> </nav> <div> <router-outlet></router-outlet> </div> </div>
app.routes.ts
const routes: Routes = [ { path: '', component: HomeComponent, pathMatch: 'full', canActivate: [AuthGuard] }, { path: 'factory', component: FactoryFormComponent, canActivate: [AuthGuard]}, //...some other { path: 'contactus', component: ContactUsComponent } ];
AuthenticateController.cs
public HttpResponseMessage Get() { return User.Identity.IsAuthenticated ? new HttpResponseMessage(HttpStatusCode.OK) : new HttpResponseMessage(HttpStatusCode.Unauthorized); }
I can hide the menu fine but homeComponent which is search textbox renders before authentication, I want to hide everything and just want to show Logo. this search for factory textbox should not be displayed and there is data like gridview at the bottom which i am not showing in this picture.
It does not redirect until Cancel is clicked...another solution is just like I hid the menu I do it on homeComponent but there are many authService calls going around which is not elegant i guess