How to check a matching route that has params? ( in route guard) - javascript

I have a route defined which has a query param called uuid
{path: 'is-protected/:uuid', component: protectedComponent, canActivate: [RouteGuardService]}
In the route guard, i need to check if the url matches and route param (:uuid) is empty or not. If the route does not have the param, i need to redirect it to home route.
I am trying using
if (state.url == 'is-protected'){
if( query param exists){
return true;
}
else {
this.route.navigate(['/']);
}
}
This wont work because the state.url does not include the query param so it will never reach in this code block.
Is there a way to check if the route including params exists and navigate accordingly?

One possible solution I implemented is create a redirection in the router itself without param and redirect it to home.
{ path: 'is-protected', redirectTo: 'home', pathMatch: 'full' }
This will handle if the query param doesnt exist . This method worked for me because I dont have any similar route or the route without param.
Now in the route guard,
if (state.url.indexOf('is-protected') > -1) {
//this route will have the query param. If it didnt, it would be redirected automatically because of redirection added in list of routes
if (condition I need to test) {
return true
} else {
this.route.navigate(['/home']);
}
}
If there is a better approach or solution, please comment. Thanks!

Getting the params
You can check the route params importing ActivatedRouter from '#angular/router' in your component or guard.
import { ActivatedRoute } from '#angular/router';
then inject it at contructor and subscribe the params.
constructor( private router: ActivatedRoute ) {
this.router.params.subscribe( (params: any) => {
console.log('params.yourParam');
});
}
Then you can acces and use the param to check what you need.
Edit:
to use throught canActivate is very similary and you can do like this:
(you can use ActivatedRouteSnapshot too if you dont need an observable)
import { ActivatedRouteSnapshot, CanActivate } from '#angular/router';
in you guard class get the params like this:
canActivate( router: ActivatedRouteSnapshot ): boolean{
if ( Object.keys(router.params).length > 0 ){
//then you have params
if ( condition you need to check){
return true
} else {
return false;
}
} else {
this.route.navigate(['/home']);
}
hope it helps you.

You should inject in your constructor route: ActivatedRouteSnapshot
You can access route parameters like this and compare them with what you expect
let id;
if(route.paramMap.has('id')){
assessmentId = route.paramMap.get("id");
}

I have only id params in route and for my case I used replace function for url
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
canActivateChild(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean {
const url: string = state.url.replace(/[0-9]/g, ':id');
// if you have route like '/posts/post/5' this will return '/posts/post/:id'
// your checking logic
}

Related

CanActivate guard for multiple users in angular

I've got a working canActivate auth-guard like this:
return this.auth.user$.map(user => {
if (user) return true;
this.router.navigate(["/login"], {queryParams: {returnUrl: state.url}});
return false;
});
}
and use it for routes like this:
{path: 'my-project', component: ToolComponent, canActivate: [AuthGuard]}
i want to have multiple users be able to work on the same project
example:
User A & B on project 1
User C & B on project 2
and so on
what's the best way to to this?
ty!
the "typical" is assing to each user a "role" (admin/user), but in your case I imagine you has severals projects. So your "user" should has a property with the project can access and the path of your router can add "data". Some like
{ path: 'project1/ComponentOne', component: Component1,
canActivate: [CheckGuard],data:{project:"project1"} },
Your "checkGuard can take account the "user" and also the "data"
#Injectable()
export class CheckGuard implements CanActivate {
constructor(private router: Router,private accountService:AccountService) { }
canActivate(activatedRouteSnapshot: ActivatedRouteSnapshot,
routerStateSnapshot: RouterStateSnapshot) {
//in activatedRouteSnapshot.data you has the "data" of the router
console.log(activatedRouteSnapshot.data)
...your logic here..
}
}

How to pass and get parameter with Router params in Angular 4.?

I want to pass an id with url using Router in Angular. And i have to fetch that value on another page. Like I have a student list. On click of edit button belongs to particular student on the list. The id of that student pass to edit student details page. After fetching that studentId I want show existing details in the input fields.
So How i can do this?
this is my example path
{ path: 'school-students-list', component: studentsListPageComponent },
{ path: 'edit-student-details', component: studentEdit },
Give the route a parameter like this:
{ path: 'edit-student-details/:id', component: studentEdit }
And then use ActivatedRoute in that component to access the route parameters. Import it from #angular/router
import { ActivatedRoute, Params } from '#angular/router';
import { Subscription } from 'rxjs/Subscription';
Inject this into the constructor
private routeSub: Subscription;
constructor(private route: ActivatedRoute) {}
On init, subscribe to route parameters
ngOnInit(): void {
this.routeSub = this.route.params.subscribe((params: Params): void => {
const id = params['id'];
});
}
Always a good idea to unsubscribe on destroy
ngOnDestroy(): void {
this.routeSub.unsubscribe();
}
And to link to this page, passing in their member ID, do this on your student listings page:
<a [routerLink]="['/edit-student-details', memberId]">Edit</a>
To navigate via a component method, inject Router from #angular/router and then when you want to navigate, use this.router.navigate(['/edit-student-details', memberId]);
Import ActivatedRoute from #angular/router
import { ActivatedRoute, Router } from '#angular/router';
Access parameter from constructor:
constructor(private route: ActivatedRoute) {
let id = +this.route.snapshot.params['id'];
// use the id here
}

angular2 get route path as title page

What's the best way of outputting a page title depending on your route path in angular2 rather than hard-coding the title, I want to output a title in the controller instead.
If user go to /dashboard and the dashboard page will have Dashboard title:
{ path: 'dashboard', component: dashComponent}
Somewhere along:
if(path==dashboard){
title:string = "Dashboard"
} else if(path==something){
title:string = "Something"
}
HTML Output:
<h1>{{title}}</h1
this logic works but repeating location.path seems a little bit tedious
if(this.location.path() == '/order-ahead'){
console.log('Dashboard')
this.title = 'Dashboard';
} else {
console.log('its something else');
this.title = 'Something Else'
}
I guess, you should use more complicated logic to achieve more sophisticated solution. For example, using CanActivated guard, something like in this ticket: Angular 2 RC4 Router get intended route before activated
I think you can follow the guidance in the docs to set the title via the Title service:
import { Title } from '#angular/platform-browser';
bootstrap(AppComponent, [ Title ])
then in your component that has access to the route use something like this:
export class AppComponent {
public constructor(private titleService: Title ) { }
public setTitle( newTitle: string) {
this.titleService.setTitle( newTitle );
}
}
Here's a link to the docs on this: https://angular.io/docs/ts/latest/cookbook/set-document-title.html
Easiest solution, subscribe to route changes in the router (example for beta 3.0-2 of router):
import { Router, Event, NavigationEnd } from '#angular/router';
constructor(protected router: Router)
{
this.router.events.subscribe(this.routeChanges.bind(this));
}
protected routeChanges(event: Event)
{
if (event instanceof NavigationEnd) {
let url = event.url;
}
}

Angular 2 router.navigate

I'm trying to navigate to a route in Angular 2 with a mix of route and query parameters.
Here is an example route where the route is the last part of the path:
{ path: ':foo/:bar/:baz/page', component: AComponent }
Attempting to link using the array like so:
this.router.navigate(['foo-content', 'bar-contents', 'baz-content', 'page'], this.params.queryParams)
I'm not getting any errors and from what I can understand this should work.
The Angular 2 docs (at the moment) have the following as an example:
{ path: 'hero/:id', component: HeroDetailComponent }
['/hero', hero.id] // { 15 }
Can anyone see where I'm going wrong? I'm on router 3.
If the first segment doesn't start with / it is a relative route. router.navigate needs a relativeTo parameter for relative navigation
Either you make the route absolute:
this.router.navigate(['/foo-content', 'bar-contents', 'baz-content', 'page'], this.params.queryParams)
or you pass relativeTo
this.router.navigate(['../foo-content', 'bar-contents', 'baz-content', 'page'], {queryParams: this.params.queryParams, relativeTo: this.currentActivatedRoute})
See also
https://github.com/angular/angular.io/blob/c61d8195f3b63c3e03bf2a3c12ef2596796c741d/public/docs/_examples/router/ts/app/crisis-center/crisis-detail.component.1.ts#L108
https://github.com/angular/angular/issues/9476
import { ActivatedRoute } from '#angular/router';
export class ClassName {
private router = ActivatedRoute;
constructor(r: ActivatedRoute) {
this.router =r;
}
onSuccess() {
this.router.navigate(['/user_invitation'],
{queryParams: {email: loginEmail, code: userCode}});
}
}
Get this values:
---------------
ngOnInit() {
this.route
.queryParams
.subscribe(params => {
let code = params['code'];
let userEmail = params['email'];
});
}
Ref: https://angular.io/docs/ts/latest/api/router/index/NavigationExtras-interface.html
As simpler as
import { Router } from '#angular/router';
constructor( private router:Router) {}
return(){this.router.navigate(['/','input']);}
Here you will be redirecting to route input .
If you wish to go to particular path with relative to some path then.
return(){this.router.navigate(['/relative','input']);}
Here on return() is the method we will be triggered on a button click
<button (click)=return()>Home

How to handle query parameters in angular 2

In my routable component I have
#RouteConfig {
{path: '/login', name: 'Login', component: LoginComponent}
}
But how do I get the query params if I go to app_url/login?token=1234?
RouteParams are now deprecated , So here is how to do it in the new router.
this.router.navigate(['/login'],{ queryParams: { token:'1234'}})
And then in the login component you can take the parameter,
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// Capture the token if available
this.sessionId = this.route.queryParams['token']
}
Here is the documentation
To complement the two previous answers, Angular2 supports both query parameters and path variables within routing. In #RouteConfig definition, if you define parameters within a path, Angular2 handles them as path variables and as query parameters if not.
Let's take a sample:
#RouteConfig([
{ path: '/:id', component: DetailsComponent, name: 'Details'}
])
If you call the navigate method of the router like this:
this.router.navigate( [
'Details', { id: 'companyId', param1: 'value1'
}]);
You will have the following address: /companyId?param1=value1. The way to get parameters is the same for both, query parameters and path variables. The difference between them is that path variables can be seen as mandatory parameters and query parameters as optional ones.
Hope it helps you,
Thierry
UPDATE: After changes in router alpha.31 http query params no longer work (Matrix params #2774). Instead angular router uses so called Matrix URL notation.
Reference https://angular.io/docs/ts/latest/guide/router.html#!#optional-route-parameters:
The optional route parameters are not separated by "?" and "&" as they
would be in the URL query string. They are separated by semicolons ";"
This is matrix URL notation — something you may not have seen before.
It seems that RouteParams no longer exists, and is replaced by ActivatedRoute. ActivatedRoute gives us access to the matrix URL notation Parameters. If we want to get Query string ? paramaters we need to use Router.RouterState. The traditional query string paramaters are persisted across routing, which may not be the desired result. Preserving the fragment is now optional in router 3.0.0-rc.1.
import { Router, ActivatedRoute } from '#angular/router';
#Component ({...})
export class paramaterDemo {
private queryParamaterValue: string;
private matrixParamaterValue: string;
private querySub: any;
private matrixSub: any;
constructor(private router: Router, private route: ActivatedRoute) { }
ngOnInit() {
this.router.routerState.snapshot.queryParams["queryParamaterName"];
this.querySub = this.router.routerState.queryParams.subscribe(queryParams =>
this.queryParamaterValue = queryParams["queryParameterName"];
);
this.route.snapshot.params["matrixParameterName"];
this.route.params.subscribe(matrixParams =>
this.matrixParamterValue = matrixParams["matrixParameterName"];
);
}
ngOnDestroy() {
if (this.querySub) {
this.querySub.unsubscribe();
}
if (this.matrixSub) {
this.matrixSub.unsubscribe();
}
}
}
We should be able to manipulate the ? notation upon navigation, as well as the ; notation, but I only gotten the matrix notation to work yet. The plnker that is attached to the latest router documentation shows it should look like this.
let sessionId = 123456789;
let navigationExtras = {
queryParams: { 'session_id': sessionId },
fragment: 'anchor'
};
// Navigate to the login page with extras
this.router.navigate(['/login'], navigationExtras);
This worked for me (as of Angular 2.1.0):
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// Capture the token if available
this.sessionId = this.route.snapshot.queryParams['token']
}
(For Childs Route Only such as /hello-world)
In the case you would like to make this kind of call :
/hello-world?foo=bar&fruit=banana
Angular2 doesn't use ? nor & but ; instead. So the correct URL should be :
/hello-world;foo=bar;fruit=banana
And to get those data :
import { Router, ActivatedRoute, Params } from '#angular/router';
private foo: string;
private fruit: string;
constructor(
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.route.params.forEach((params: Params) => {
this.foo = params['foo'];
this.fruit = params['fruit'];
});
console.log(this.foo, this.fruit); // you should get your parameters here
}
Source : https://angular.io/docs/ts/latest/guide/router.html
Angular2 v2.1.0 (stable):
The ActivatedRoute provides an observable one can subscribe.
constructor(
private route: ActivatedRoute
) { }
this.route.params.subscribe(params => {
let value = params[key];
});
This triggers everytime the route gets updated, as well: /home/files/123 -> /home/files/321
The simple way to do that in Angular 7+ is to:
Define a path in your ?-routing.module.ts
{ path: '/yourpage', component: component-name }
Import the ActivateRoute and Router module in your component and inject them in the constructor
contructor(private route: ActivateRoute, private router: Router){ ... }
Subscribe the ActivateRoute to the ngOnInit
ngOnInit() {
this.route.queryParams.subscribe(params => {
console.log(params);
// {page: '2' }
})
}
Provide it to a link:
<a [routerLink]="['/yourpage']" [queryParams]="{ page: 2 }">2</a>
Angular 4:
I have included JS (for OG's) and TS versions below.
.html
<a [routerLink]="['/search', { tag: 'fish' } ]">A link</a>
In the above I am using the link parameter array see sources below for more information.
routing.js
(function(app) {
app.routing = ng.router.RouterModule.forRoot([
{ path: '', component: indexComponent },
{ path: 'search', component: searchComponent }
]);
})(window.app || (window.app = {}));
searchComponent.js
(function(app) {
app.searchComponent =
ng.core.Component({
selector: 'search',
templateUrl: 'view/search.html'
})
.Class({
constructor: [ ng.router.Router, ng.router.ActivatedRoute, function(router, activatedRoute) {
// Pull out the params with activatedRoute...
console.log(' params', activatedRoute.snapshot.params);
// Object {tag: "fish"}
}]
}
});
})(window.app || (window.app = {}));
routing.ts (excerpt)
const appRoutes: Routes = [
{ path: '', component: IndexComponent },
{ path: 'search', component: SearchComponent }
];
#NgModule({
imports: [
RouterModule.forRoot(appRoutes)
// other imports here
],
...
})
export class AppModule { }
searchComponent.ts
import 'rxjs/add/operator/switchMap';
import { OnInit } from '#angular/core';
import { Router, ActivatedRoute, Params } from '#angular/router';
export class SearchComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.route.params
.switchMap((params: Params) => doSomething(params['tag']))
}
More infos:
"Link Parameter Array"
https://angular.io/docs/ts/latest/guide/router.html#!#link-parameters-array
"Activated Route - the one stop shop for route info" https://angular.io/docs/ts/latest/guide/router.html#!#activated-route
For Angular 4
Url:
http://example.com/company/100
Router Path :
const routes: Routes = [
{ path: 'company/:companyId', component: CompanyDetailsComponent},
]
Component:
#Component({
selector: 'company-details',
templateUrl: './company.details.component.html',
styleUrls: ['./company.component.css']
})
export class CompanyDetailsComponent{
companyId: string;
constructor(private router: Router, private route: ActivatedRoute) {
this.route.params.subscribe(params => {
this.companyId = params.companyId;
console.log('companyId :'+this.companyId);
});
}
}
Console Output:
companyId : 100
According to Angular2 documentation you should use:
#RouteConfig([
{path: '/login/:token', name: 'Login', component: LoginComponent},
])
#Component({ template: 'login: {{token}}' })
class LoginComponent{
token: string;
constructor(params: RouteParams) {
this.token = params.get('token');
}
}
Angular 5+ Update
The route.snapshot provides the initial value of the route parameter
map. You can access the parameters directly without subscribing or
adding observable operators. It's much simpler to write and read:
Quote from the Angular Docs
To break it down for you, here is how to do it with the new router:
this.router.navigate(['/login'], { queryParams: { token:'1234'} });
And then in the login component (notice the new .snapshot added):
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sessionId = this.route.snapshot.queryParams['token']
}
In Angular 6, I found this simpler way:
navigate(["/yourpage", { "someParamName": "paramValue"}]);
Then in the constructor or in ngInit you can directly use:
let value = this.route.snapshot.params.someParamName;

Categories