Angular2 routing canActivate and AuthGuard (JWT) with user role parameter - javascript

In this exaple project with JWT authentication we se how to allow only authenticated users to some route:
import { RouterConfig } from '#angular/router';
import { Home } from './home';
import { Login } from './login';
import { Signup } from './signup';
import { AuthGuard } from './common/auth.guard';
export const routes: RouterConfig = [
{ path: '', component: Login },
{ path: 'login', component: Login },
{ path: 'signup', component: Signup },
{ path: 'home', component: Home, canActivate: [AuthGuard] },
{ path: '**', component: Login },
];
I would like make step further and also indicate what user role have 'access' to route - but I don't know how to pass argument to canActivate AuthGuard (src). So I would like to achieve something like this (for instance I have two roles: Admin and Employee):
{ path: 'home', component: Home, canActivate: [AuthGuard] },
{ path: 'users', component: AdminUsers, canActivate: [AuthGuard('Admin')] },
{ path: 'users', component: Employees, canActivate: [AuthGuard('Employee')] },
Where my AuthGuard could look something like this (where userRole(= Admin or Employee or null) is passed parameter to AuthGuard):
#Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(userRole) {
if (!userRole || JWT.user().role == userRole) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
where JWT.user.role is helper which read user role stored in JWT token. Is there a way to do something similar like above idea?

You can set the data parameter of the route with the role like this
const appRoutes: Routes = [
{
path: 'account/super-secure',
component: SuperSecureComponent,
canActivate: [RoleGuard],
data: { roles: ['super-admin', 'admin'] }
}];
and then have this in canActivate of RoleGuard:
canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
let roles = route.data["roles"] as Array<string>;
return (roles == null || roles.indexOf("the-logged-user-role") != -1);
}
I think this could be another way of doing it instead of creating guard for every role. I would actually take this rout since it requires less code and handles the problem very nicely.

The signature for CanActivate won't allow you to pass a userRole like you want to. https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/router/src/interfaces.ts#L54
It's probably best to do separate classes for each of your user role cases. That's the guidance in the official docs too: https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html

NOTE: applicable for angular-rc.4 <
#KamilKiełczewski, #NikolayRusev,
added in route additional data with array of routes:
...
{
path: "customers",
component: CustomersCmp,
data: { roles: ["admin"] }
},
...
and in CanActivate you can get path from first parameter, search the same path in route config and get your described roles from data:
public canActivate(route: ActivatedRouteSnapshot): boolean {
let path = route._urlSegment.pathsWithParams[0].path;
let roles;
if (route._routeConfig.path == path) {
roles = route._routeConfig.data.roles
} else {
roles = route._routeConfig.children.find(_route => _route.path == path).data.roles;
}
if (...) {
return true;
}
return false;
}
Of course it would be better to avoid private properties, and you can, but I cannot remember how I exactly done it.
But for my porposes I redid it in different way. The huge disadvantage of this approach, I mean for role based guard, is that every user with different roles can see all of the routes if you render them in a component automatically not manually.
you can extend router-outlet
http://www.captaincodeman.com/2016/03/31/angular2-route-security/
https://medium.com/#blacksonic86/authentication-in-angular-2-958052c64492#.cxgoan9go

Related

What makes Keycloak's AuthGuard class throw this error in an Angular 14 app?

I am working on an app in Angular 14 that requires authentication/authorization, reason for witch I use Keycloak Angular. I need to guard certain routes.
As per the instructions, I have first installed Keycloak Angular with:
npm install keycloak-angular keycloak-js
In shared/auth-guard.service.ts I have:
import { Injectable } from '#angular/core';
import {
ActivatedRouteSnapshot,
Router,
RouterStateSnapshot
} from '#angular/router';
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
#Injectable({
providedIn: 'root'
})
export class AuthGuard extends KeycloakAuthGuard {
constructor(
protected override readonly router: Router,
protected readonly keycloak: KeycloakService
) {
super(router, keycloak);
}
public async isAccessAllowed(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
if (!this.authenticated) {
await this.keycloak.login({
redirectUri: window.location.origin + state.url
});
}
}
}
I have imported the above service in my application's routing module:
import { AuthGuard } from './shared/auth-guard.service';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent },
{ path: 'profile', component: ProfileComponent }
];
The problem
Importing the AuthGuard service throws the error:
Property 'isAccessAllowed' in type 'AuthGuard' is not assignable to the same property in base type 'KeycloakAuthGuard'.
The error refers to the isAccessAllowed() method in the auth-guard.service.ts file.
Questions
What is causing this error?
What is the easiest and most reliable way to fix it?
You method implementation does not match the type definition of the base class because you do not return anything if the user is authenticated.
The method definition from keycloak-angular for isAccessAllowed():
abstract isAccessAllowed(route: ActivatedRoute, state: RouterStateSnapshot): Promise<boolean | UrlTree>;
The method has a return type of Promise<boolean | UrlTree>.
You need to return a value if the user is already authenticated. They can access the route and the guard should indicate that. Try making this change:
public async isAccessAllowed(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
if (!this.authenticated) {
await this.keycloak.login({
redirectUri: window.location.origin + state.url
});
}
return true;
}
EDIT:
You add it to your routes like so:
import { AuthGuard } from './shared/auth-guard.service';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'login', component: LoginComponent },
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] }
];
See the Angular docs on route guards.

How to change VueRouter source file dynamicly?

Hello i have a project it contain multiple role (VueJs+Laravel), i'm using laravel as a back-end and vuejs as a front-end,
i have three diffrent role (User,Modirator,Editor).
this is my code in app.js
// VueRouter
import VueRouter from 'vue-router';
import routes from './routes.js';
Vue.use(VueRouter);
var router = new VueRouter({
mode: 'history',
routes
})
this is my routes file:
let routes = [
// General
{ path: '/about', component: require('./components/Home/About.vue').default },
{ path: '/pasword-change', component: require('./components/ChangePassword.vue').default },
// User
{ path: '/User', component: require('./components/User/Dashboard.vue').default },
// Modirator
{ path: '/Modirator', component: require('./components/Modirator/Dashboard.vue').default },
// Editor
{ path: '/Editor', component: require('./components/Editor/Dashboard.vue').default },
// Error
{ path: '*', component: require('./components/Errors/404.vue').default} },
]
export default routes
after login i want to check it in back-end as a ajax request if the role is user use (routes-user.js) elseif is a modirator use (routes-mod.js) else (routes.js).
i dont want to show /user /modirator /editor in client, but i want to check after login and each one show role component in root url /.
thanks for help.
thanks for help....
I tested something similar to your requirement for normal component passing and lazy loading component in Vuex and this works. Below is my code what I am trying to do is have a variable 'unauthorized' and based on which I an loading different component using javascript ternary operator or javascript template string.
import Vue from 'vue'
import Router from 'vue-router'
import Auth from './views/Auth.vue'
import Board from './views/Board.vue'
Vue.use(Router)
let unauthorized = true;
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/auth',
name: 'authenticate',
component: unauthorized ? Auth : Board
},
{
path: '/',
name: 'home',
component: () => import(`./views/${unauthorized ? 'Auth.vue': 'Board.vue'}`)
}
]
})
Specific Solution
As per your requirement, you can store a variable('access-type') in local storage based on whether you log in as 'moderator' or 'user' or 'editor' and then fetch it in router.js file and use template string feature to conditionally change the component path.
Do let me know if you need more help.
You could add meta data to your routes to solve the problem and the check the meta data before you're entering a route:
{ path: '/about', component: require('./components/Home/About.vue').default },
{ path: '/pasword-change', component: require('./components/ChangePassword.vue').default },
// User
{ path: '/User', component: require('./components/User/Dashboard.vue').default, meta: {authorize: ["Admin"]} },
Then add the following method to you router:
router.beforeEach((to, from, next) => {
const { authorize } = to.meta
// get currently logged in user (in my case it's coming from vuex)
const currentUser = store.getters['authentication/user']
if (!currentUser && to.path !== '/login') {
// not logged in so redirect to login page with the return url
return next({ path: '/login', query: { returnUrl: to.path } })
}
if (authorize) {
// check if route is restricted by role
if (authorize.length && !authorize.some(r => currentUser.roles.includes(r))) {
// role not authorised so redirect to home page
return next({ path: '/' })
}
}
next()
})

Routing submenu elements Angular 2

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.

redirectTo not working when using canActivate guard

The redirectTo property isn't working in my Angular 2 app. I have the following routes in my app.routing.ts:
const routes: Routes = [
{ path: '', redirectTo: '/page/1', pathMatch: 'full' },
{ path: 'page', loadChildren: 'app/modules/page/page.module#PageModule' }
]
export const routing = RouterModule.forRoot(routes);
Then, in my page.routing.ts, I have the following:
const pageRoutes: Routes = [
{ path: ':id', component: PageComponent, canActivate: [LoginGuard] }
];
export const pageRouting = RouterModule.forChild(pageRoutes);
Every time I access the home page it displays the LoginComponent for a second, then it disappears. However, it should redirect to the PageComponent.
Why isn't that happening? Why the LoginComponent is being loaded (even if it's only for a brief second) if the user is already logged in?
Here's my LoginGuard:
#Injectable()
export class LoginGuard implements CanActivate {
constructor(private af: AngularFire, private router: Router) {}
canActivate(): Observable<boolean> {
return this.af.auth.map(auth => {
if (auth === null) {
this.router.navigate(['/login']);
return false;
} else {
return true;
}
}).first();
}
}
EDIT: Temporarily, I changed the LoginComponent to redirect to the PageComponent if a user is logged in. I still wonder, though, why redirectTo isn't working.
I don't know exactly why this is happening, but I believe if you check the LoginGuard before the PageModule loads, it will work.
app.routing.ts
const routes: Routes = [
{ path: '', redirectTo: '/page/1', pathMatch: 'full' },
{
path: 'page',
// Call the guard before the module is loaded
canLoad: [ LoginGuard ]
loadChildren: 'app/modules/page/page.module#PageModule'
}
]
export const routing = RouterModule.forRoot(routes);
LoginGuard
#Injectable()
export class LoginGuard implements CanActivate, CanLoad {
constructor(private af: AngularFire, private router: Router) {}
// Add this method to validade the canLoad
canLoad(route: Route): Observable<boolean> {
return this.canActivate();
}
canActivate(): Observable<boolean> {
return this.af.auth.map(auth => {
if (auth === null) {
this.router.navigate(['/login']);
return false;
} else {
return true;
}
}).first();
}
}
You should NOT navigate inside a Guard
This is happening because you call this.router.navigate(['/login']); directly from your route guard which initializes a new route navigation on top of the one currently running.
You create a "race" between two navigations; my guess is the one to /login' wins because the other one has to lazy load the module (takes some time). But after the loading is done, it changes to that route afterwards, hence the "flashing" login popup.
You should NOT navigate inside a Guard, instead you should always return either a boolean (to allow navigate true/false) or a UrlTree if you want to redirect/change the route. The Guard returns the value and the router will then change navigation to the provided UrlTree for you inside the ongoing/triggered navigation and you won't get any race.
So change your method like this, and it will work correct.
canActivate(): Observable<boolean|UrlTree> {
return this.af.auth.map(auth => {
if (auth === null) {
return this.router.parseUrl('/login');
}
return true;
}).first();
}
You should see it like this, if you would call this.router.navigate in several route guards then the router wouldn't know where to navigate to, by returnin a UrlTree this problem is resolved. See also a related question/answer here

How to redirect to an external URL from angular2 route without using component?

I would like to create an external redirect, but to make all routes consistent I think it would be nice to do everything(including external redirects) under Router States configuration.
so:
const appRoutes: Routes = [
{path: '', component: HomeComponent},
{path: 'first', component: FirstComponent},
{path: 'second', component: SecondComponent},
{path: 'external-link', /*would like to have redirect here*/}
];
UPD: and I don't want to use empty component for this case like #koningdavid suggested. This solution looks really weird for me. It should be something really easy to implement for such case, without virtual components.
You can achieve what you want with a trick using the resolve option of a route. Resolve is some data value that Angular2 will obtain for the route to be initialized. More details you can find here in the official documentation.
I have tried this approach and it does work. Example:
Add this to the provider section (plus import the required classes from Routing)
#NgModule({
providers: [
{
provide: 'externalUrlRedirectResolver',
useValue: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
{
window.location.href = (route.data as any).externalUrl;
}
}
]
})
Then you can define your route like this:
{
path: 'test',
component: AnyRandomComponent,
resolve: {
url: 'externalUrlRedirectResolver'
},
data: {
externalUrl: 'http://www.google.com'
}
}
This will redirect to the external URL. It's a bit of a hackish way really. I tried to achieve the result without using the component at all, but you have to use either redirectTo or component or children or loadChildren. redirectTo won't trigger the resolve and I am not sure about children, though you can experiment.
You can implement it in a nice class rather than direct function in provider. More info in the documentation (see reference above).
P.S. I would really rather use a redirect component myself I think. Just use the trick with the data and getting the state from the router with externalUrl to get this as a parameter.
You can create a RedirectGuard:
import {Injectable} from '#angular/core';
import {CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot} from '#angular/router';
#Injectable({
providedIn: 'root'
})
export class RedirectGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
window.location.href = route.data['externalUrl'];
return true;
}
}
Import it in app.module:
providers: [RedirectGuard],
And define your route:
{
path: 'youtube',
canActivate: [RedirectGuard],
component: RedirectGuard,
data: {
externalUrl: 'https://www.youtube.com/'
}
}
As far as I know NG2 router doesn't support external redirecting. You could create a redirect component as a workaround.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'redirect',
template: 'redirecting...'
})
export class RedirectComponent implements OnInit {
constructor() { }
ngOnInit() {
window.location.href = 'http://www.redirecturl.com'
}
}
And use that in your routing
{ path: 'login', component: RedirectComponent, pathmath: 'full'},
Hmm...
I think you can simply request the URL instead of calling ng2 Router...
For example...
External
instead of
<a routerLink="/someRoute" routerLinkActive="active">External</a>
OR
window.location.href = 'http://www.example.com'
instead of
this.router.navigate( [ '/someRoute', 'someParam' ] );
Right...?
just use:
{
path: 'external-link',
loadChildren: () => new Promise( () => { if(window.location.href.match(/external-link/) ) window.location.href = 'https://external-link.com/'; } )
},
The Router can't redirect externally. An external resource can't be a state of the app.
If it's only for clarity, keeping all the routes visible in the one spot, you could define another constant array with all the external paths in the same file as the routes.
I assume you don't wanna create a component for every single url, which is why you are looking to do it without a component...
So you can try creating a function that generates the component object for you...
For example...
function generateLinkingComponent( url ) {
// Generate your component using koningdavid's code
// replace 'http://www.redirecturl.com' with url param
// and return it...
}
And add it like this in your router config...
const appRoutes: Routes = [
{path: '', component: HomeComponent},
{path: 'first', component: FirstComponent},
{path: 'second', component: SecondComponent},
{path: 'external-link', component: generateLinkingComponent( 'http://example.com' )},
{path: 'client-login', component: generateLinkingComponent( 'http://client-login.example.com' )},
{path: 'admin-login', component: generateLinkingComponent( 'http://admin.example.com' )},
];
This will be easy with JS... but not sure how one can return a class in a function in typeScript...
Hope that helps...
Wrapping up Ilya's answer:
Add this module.
import { Component, Injectable, NgModule } from '#angular/core';
import { ActivatedRouteSnapshot, Resolve } from '#angular/router';
#Component({
template: ''
})
class ExternalLinkComponent {
constructor() {
}
}
#Injectable()
class ExternalLinkResolver implements Resolve<any> {
resolve(route: ActivatedRouteSnapshot): any {
window.location.href = route.data.targetUri;
return true;
}
}
export class ExternalRoute {
data: {
targetUri: string;
};
path: string;
pathMatch = 'full';
resolve = { link: ExternalLinkResolver };
component = ExternalLinkComponent;
constructor(path: string, targetUri: string) {
this.path = path;
this.data = { targetUri: targetUri };
}
}
#NgModule({
providers: [ ExternalLinkResolver ],
declarations: [ExternalLinkComponent]
})
export class ExternalRoutesModule { }
Then import ExternalRoutesModule and add instances of ExternalRoute.
const childRoutes: Routes = [
new ExternalRoute('', '/settings/account'),
{ path: 'staff-profiles', component: StaffProfilesComponent},
{ path: 'staff-assignments', component: StaffAssignmentsComponent}
];
const routes: Routes = [
{ path: '', component: BaseComponent, children: childRoutes }
];
#NgModule({
imports: [ ExternalRoutesModule, RouterModule.forChild(routes) ],
exports: [ RouterModule ]
})
export class SettingsRoutingModule { }
Note I'm mounting the submodule routes via loadChildren in this example.
You can use the NavigationEnd event.
import { NavigationEnd, Router } from '#angular/router';
app.component.ts
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event.url.includes('faq')) {
// open in the same tab:
window.location.href = 'https://faq.website.com';
// open a new tab:
// window.open('https://faq.website.com', '_blank');
// and redirect the current page:
// this.router.navigate(['/']);
}
}
});
P.S. Don't forget to remove your route from the AppRoutingModule.
Here is a code that should work for you without a lot of issues. FYI the router events error handler can be put anywhere irrespective of placement in the component.
app.component.html
Angular Port is in 4200
<a routerLink="/test">Main Link - 1</a> |
<a [routerLink]="getLinkWithExternal({url: '/test', external:false})">Other Link - 1a</a> |
<a [routerLink]="getLinkWithExternal({url: 'http://localhost:4211', external:true})">Other Link - 1b</a> |
<a [routerLink]="getLink({url: '/test'})">Other Link - 1a</a> |
<a [routerLink]="getLink({url: 'http://localhost:4211'})">Other Link - 1b</a> |
<a style="cursor: pointer; text-decoration: underline;" (click)="routeLink('/test')">Other Link - 1c</a> |
<a style="cursor: pointer; text-decoration: underline;" (click)="routeLink('http://localhost:4211')">Other Link - 1d</a>
<router-outlet></router-outlet>
app.component.ts
import { Component } from '#angular/core';
import { NavigationEnd, Router } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(private router: Router) { }
// RECOMMENDATION - Add following in menus of each microservice (individual and different)
// external: true
// Will make it a better menu structure for each microservice
// If Single and same menu for all microservices then remove external === true
// Logic One
getLinkWithExternal(sidebarnavLink: any) {
this.router.errorHandler = function (error: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return null;
}.bind(sidebarnavLink);
return [sidebarnavLink.url];
}
getLinkWithExternalWithEventSubscribe(sidebarnavLink: any) {
this.router.events.subscribe(function (event) {
if (event instanceof NavigationEnd) {
if (event.url.includes('http')) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return this.router.navigateByUrl(sidebarnavLink.url);
// return this.router.navigate([sidebarnavLink.url]);
}
return this.router.navigateByUrl(sidebarnavLink.url);
// return this.router.navigate([sidebarnavLink.url]);
}
}.bind(sidebarnavLink))
}
getLinkWithExternalImplementationTwoWithNoRouteError(sidebarnavLink: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http") && sidebarnavLink.external === true) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return [sidebarnavLink.url];
}
// Logic Two
getLink(sidebarnavLink: any) {
this.router.errorHandler = function (error: any) {
if (!sidebarnavLink.url.includes(window.location.origin.toString()) && sidebarnavLink.url.includes("http")) {
window.location.href = sidebarnavLink.url.toString();
return true;
}
return null;
}.bind(sidebarnavLink);
return [sidebarnavLink.url];
}
// Logic Three
routeLink(lnk: any) {
if (lnk.includes("http")) {
console.log("Test");
window.location.href = lnk;
return true;
}
return this.router.navigateByUrl(lnk);
// return this.router.navigate([lnk]);
}
}

Categories

Resources