Angular 8 routing changes unintentionally querystring order - javascript

Building an app using Angular 8 as landing page that accepts dynamic query strings within the redirect link which contains some query string keys as number like: 42=17 so for example when I hit in the browser the full link as follow with:
http://localhost:4200/success?id1=123&42=17&hash=qwertzuiop
Result: It changed the sequence unintentionally to:
http://localhost:4200/success?42=17&id1=123&hash=qwertzuiop
Expected: To maintain the same order of the query string as I need to check the hash string against the original url if it's altered and of course when the sequence changes, the hash function result changes consequently.
Code sample:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { SuccessComponent } from './success/success.component';
import { NotFoundComponent } from './not-found/not-found.component';
const routes: Routes = [
{ path: 'success', component: SuccessComponent },
{ path: '**', component: NotFoundComponent }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
success.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
#Component({
selector: 'app-success',
templateUrl: './success.component.html',
styleUrls: ['./success.component.scss']
})
export class SuccessComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private router: Router) { }
ngOnInit() {
console.log(this.route.snapshot.queryParams);
// {42: "17", id1: "123", hash: "qwertzuiop"}
console.log(this.router.routerState.snapshot.url);
// /success?42=17&id1=123&hash=qwertzuiop
}
}
Any clue if I can intercept the original URL before matching angular routes and navigating?

Related

Angular Route with encoded query params not being resolved

In my Angular 10 application I have a route like this
http://localhost:4200/employee/enrollments?number=189930097&city=Chicago
Sometimes the URL is being encoded as
http://localhost:4200/employee/enrollments%3Fnumber%3D189930097%26city=Chicago
and router fails to find a match. Is there a way to fix this decoding issue and make it resolve always?
Update:
I added my footer component in which I am using routerLink that updates the current URL
EmployeeRoutingModule:
export const enrollmentManagementRoutes: Routes = [
{
path: 'enrollments',
component: EnrollmentSearchComponent,
canActivate: [EmployeeAuthGuardService],
}
];
#NgModule(
{
imports: [
RouterModule.forChild(enrollmentManagementRoutes)
],
exports: [
RouterModule
]
})
export class EmployeeRoutingModule
{
}
FooterComponent
import {Component, OnInit} from '#angular/core';
import {NavigationEnd, Router} from '#angular/router';
import {environment} from '../../../environments/environment';
#Component({
selector: 'app-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit
{
appVersion: any;
currentUrl='/';
constructor(private router: Router)
{
}
ngOnInit()
{
this.appVersion = environment.VERSION;
//Update Need Assistance link URL, this prevents default URL being '/'
this.router.events.subscribe(data=>
{
if(data instanceof NavigationEnd)
{
this.currentUrl=data.url+'';
}
});
}
navigateByUrl()
{
this.router.navigateByUrl(this.currentUrl);
}
}
Footer Component HTML:
<a class=" col-sm-12 col-xs-12 col-md-auto request-help-link" id="request-help-link" rel="noopener noreferrer"
[routerLink]="currentUrl" style="font-size: 20px" >
Need Assistance? Click here
</a>
Would it not make more sense to use a route parameter than a query string?
export const enrollmentManagementRoutes: Routes = [
{
path: 'enrollments:number',
component: EnrollmentSearchComponent,
canActivate: [EmployeeAuthGuardService],
}
];
and then route to http://localhost:4200/employee/enrollments/189930097
and in your component you can use the ActivatedRoute service to get the param.
https://angular.io/api/router/ActivatedRoute
Have you tried to use something like custom serializer?
serializer.ts
export class CustomUrlSerializer implements UrlSerializer {
parse(url: any): UrlTree {
const dus = new DefaultUrlSerializer();
return dus.parse(url);
}
serialize(tree: UrlTree): any {
const dus = new DefaultUrlSerializer();
const path = dus.serialize(tree);
// use your regex to replace as per your requirement.
path.replace(/%3F/g, '?');
path.replace(/%3D/g, '=');
return path;
}
}
and then in App module
...
providers: [
{provide: UrlSerializer, useClass: CustomUrlSerializer}
],
...

Angular Routing not working when creating an HttpModule object

I am trying to use angular routing to route to a new url when a button is clicked. I also need to use the module HttpClient to call some calls to the backend. However, whenever I create a HttpClient object, the routing doesn't work and it routes to a blank page with no url extension. When I delete the object, the routing works again. Anyone know how to overcome this? Here are some of my code snippets.
agent-page-component.ts (I create a Agent Service in the constructor)
import { Router} from "#angular/router";
import { Agent } from '../../models/agent.model'
import { AgentService } from '../../services/agent.service';
import { Subject, Subscription } from 'rxjs';
#Component({
selector: 'app-agent-page',
templateUrl: './agent-page.component.html',
styleUrls: ['./agent-page.component.css']
})
export class AgentPageComponent implements OnInit {
agents: Agent[] = [];
private agentSub: Subscription;
constructor(private agentService: AgentService){}
ngOnInit() {
this.agentService.getAgents();
this.agentSub = this.agentService.getAgentUpdateListener().subscribe((agents: Agent[]) => {
this.agents = agents;
});
}
ngOnDestroy() {
this.agentSub.unsubscribe();
}
}
agent.service.ts (this is where I import an HttpClient)
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs';
import { HttpClient, HttpClientModule } from '#angular/common/http';
#Injectable({providedIn: 'root'})
export class AgentService {
private agents: Agent[] = [];
private agentsUpdated = new Subject<Agent[]>();
constructor(private http: HttpClient){}
getAgentUpdateListener() {
return this.agentsUpdated.asObservable();
}
getAgents(){
this.http.get<{message: string, agents: Agent[]}>('http://localhost:3000/agents/Breach').subscribe((agentList) => {
this.agents = agentList.agents;
})
}
}
app-routing.module.ts
import { Routes, RouterModule } from '#angular/router';
import { AgentPageComponent } from './components/agent-page/agent-page.component';
import { HomePageComponent } from './components/home-page/home-page.component';
const routes: Routes = [
{path: 'agents', component: AgentPageComponent},
{path: '', component: HomePageComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

How do I execute this redirect based on whether or not authentication takes place in a Angular 9 application?

Im am working on an Angular 9 application that uses OneLogin for authentication purposes.
In the auth.component.ts file I have an authentication service that I use in the authentication component:
import { AuthService } from 'path/to/core/services/auth/auth.service';
import { AuthApiService } from 'path/to/core/core/services/auth/auth-api.service';
import { Component, OnInit } from '#angular/core';
import { authCodeFlowConfig } from 'path/to/config/onelogin-api/config-auth.component';
#Component({
selector: 'auth',
templateUrl: './assets/auth.component.html',
styleUrls: ['./assets/auth.component.scss']
})
export class AuthComponent implements OnInit{
constructor(private _authService: AuthService) {
}
startAuthentication() {
this._authService.startAuthentication();
}
ngOnInit(): void {
this.startAuthentication();
}
}
In auth.service.ts I have the startAuthentication() method:
startAuthentication(): Observable<any> {
const {issuer, redirectUri, clientId, responseType, scope} = authCodeFlowConfig;
const url = `someURL`;
this.redirectTo(url);
return of(false);
}
redirectTo(url: string): void {
window.location.href = url;
}
In the app.module.ts file I have this array of routes:
import { AuthService } from './core/services/auth/auth.service';
// more imports
const appRoutes: Routes = [
{
path : 'myroute',
redirectTo: 'myroute'
},
{
path: 'auth',
component: AuthComponent
}
];
In other words, I want the application to reach a certain url if login is successful and otherwise redirect to the login form.
What I want to happen is: when login is sucessful - in other words, when startAuthentication() is executed - there should be a redirect to myroute.
I tried {path: 'auth', component: AuthComponent, startAuthentication:[AuthService]} bit it fails.
What am I doing wrong?
As I don't have any further information about your StartAuthentication method, I'd say that you should inject the router service in your component and navigate using it:
import { Router } from '#angular/router';
...
constructor(
private _authService: AuthService,
private _router: Router) {}
startAuthentication() {
this._authService.startAuthentication();
this._router.navigate(['/', 'myroute']);
}

Redirecting to maintenance page

I am looking for ways of redirecting a page to the maintenance page in angular but i am new and am research different methods for turning on maintenance mode
i found a possible solution here: # the approved answer
Angular JS redirect to page within module config
however i don't know how to implement it
if there someone who could explain it, i would appreciate it greatly
using an authGuard will solve this problem
auth-guard.service.ts file:
import { Injectable } from '#angular/core';
import { CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot } from '#angular/router';
import { AuthService } from './auth.service';
import { Observable } from 'rxjs';
#Injectable()
export class AuthGuardMaintenance implements CanActivate {
constructor(
private authService: AuthService, private router: Router
) {}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
if (this.authService.inMaintenance()) {
alert('This Site Is Still Under Maintenance')
this.router.navigate(['/maintenance']);
return false;
} else {
this.router.navigate(['/']);
return true;
}
}
}
auth.service file:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class AuthService {
constructor() { }
inMaintenance() {
return false;
}
}
then import it in the app.module.ts file and add it to providers
then import the auth guard to the app-routing.module.ts file add the property
canActivate: [AuthGuardMaintenance]
to the the root route
eg
export const routes: Routes = [
{ path: '', component: MainComponent, canActivate: [AuthGuardMaintenance] },
{ path: 'maintenance', component: MaintenanceViewComponent },
{ path: '**', component: PageNotFoundComponent },
];

Capture redirect route with guard in Angular2

I'm having trouble capturing the original navigating route using a guard in Angular 2.
My site consists of a core module protected by an authorization guard, and a login page that's unprotected.
The core module has it's own sub routes defined in it's own app routing file, and any undefined routes are redirected to the root path.
Here's my top level routing module.
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AuthGuard } from './auth';
const routes: Routes = [
// Login module is public
{ path: 'login', loadChildren: 'app/auth/auth.module#AuthModule' },
// Core route protected by auth guard
{ path: '', loadChildren: 'app/core/core.module#CoreModule', canLoad: [AuthGuard] },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
And here is the AuthGuard class.
import { Injectable } from '#angular/core';
import { Router, CanLoad, Route } from '#angular/router';
import { AuthService } from './auth.service';
#Injectable()
export class AuthGuard implements CanLoad {
constructor(
private authService: AuthService,
private router: Router
) {}
canLoad(route: Route): boolean {
this.authService.redirectUrl = `/${route.path}`;
console.log('path:' + route.path);
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
This is a pretty straightforward login/redirect scheme, however the route.path value is always empty, regardless of what URL I navigate to. I have a hunch that it has something to do with the { path: '**', redirectTo: '' } route but I'm not sure.
I don't want to use canActivate because I only want the main module loaded if the user is actually logged in.
What I expected was that if I navigate to /foobar then route.path would be set to foobar in the AuthGuard class but it is not. It is always empty, thus I am unable to do a correct redirect after the user logs in.
Try adding the pathMatch: 'full' like this:
{path: '**', redirectTo: '', pathMatch: 'full'}
or
import {CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot} from "#angular/router";
import { Subscription, Observable } from "rxjs/Rx";
export class HomepageGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
console.log(`[homepage.guard.ts]-[canActivate()]`);
console.log(route);
console.log(state);
// are you allowed to continue
return true;
}
}

Categories