I have the following route-
const routes: Routes = [
{
path: '',
component: ParentComponent,
children: [
{
path: ':id',
component: ChildComponent,
},
]
}
];
in the constructor of the parent I want to navigate to some id, for example 'test'.
I tried this-
constructor(private router: Router) {
this.router.navigate(['child']);
}
and this-
constructor(private router: Router) {
this.router.navigate(['/child']);
}
and this-
constructor(private router: Router) {
this.router.navigate(['./child']);
}
and this-
constructor(private router: Router) {
this.router.navigate(['../child']);
}
my url is - http://localhost:4200/parent.
but all of this options I go to http://localhost:4200/child instead of http://localhost:4200/parent/child
Any idea why? how can I make it relative to the parent?
Because navigate takes in absolute paths.
You have to explicitly tell it to be relative :
constructor(
private router: Router,
private route: ActivatedRoute
) {
this.router.navigate(['child'], { relativeTo: this.route });
}
Related
How can I get my service variable in routing file.
I made a UserService which has a variable user and I want to access that variable in my routing file.
Below is my approach which didn't work:
In routing file, I wrote:
const steps = userService.user.onboardingStatus; //shows error ---> *cannot find name userService*
const routes: Routes = [
{
path: 'welcome',
component: WelcomeComponent,
},
{
path: 'product-selection',
component: ProductSelectionComponent,
canActivate: [ClientRoutesGuard],
data: {
isStepAccessible: steps.['welcome'].status, //will return true or false
},
},
]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ClientRoutingModule {
constructor(public userService: UserService) {}
}
Thanks in advance!
If you want the user to be able to go to the 'product-selection' route only when steps['welcome'].status is true, you should create a guard for it. For example:
export class ProductSelectionGuard implements CanActivate {
constructor(private userService: UserService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.userService.user.steps['welcome'].status;
}
}
Then include your guard in the canActivate array for your route:
// ... other routes
{
path: 'product-selection',
component: ProductSelectionComponent,
canActivate: [ClientRoutesGuard, ProductSelectionGuard],
// data: {
// isStepAccessible: steps.['welcome'].status, //will return true or false
// },
},
I have angular 8 application and I am using identity server. And I have a home component and a navbar component. And on a navbar component you have a login button what the user will directed to the login page.
But what I want now is that if you go to home: http://localhost:4200/home. That the use will directly go to the login page.
So this is the home component:
export class HomeComponent implements OnInit {
constructor(public oidSecurityService: OidcSecurityService) {}
ngOnInit() {
this.login();
console.log(this.oidSecurityService.getState);
}
login() {
this.oidSecurityService.authorize();
}
}
And this is the navbar component:
export class NavBarComponent implements OnInit, OnDestroy {
currentUser$: Observable<any> ;
userData: any;
isAuthenticated$: Observable<boolean> ;
isAuthenticated: boolean;
constructor(
public oidSecurityService: OidcSecurityService,
private _oidcConfigService: OidcConfigService,
public platform: Platform
) {}
ngOnInit(): void {
this.isAuthenticated$ = this.oidSecurityService.isAuthenticated$;
this.oidSecurityService.checkAuth().subscribe(auth => {
console.log('is authenticated', auth);
});
this.oidSecurityService.userData$.subscribe(userData => {
console.log(this.userData = userData);
});
this.isAuthenticated$.subscribe((data) => {});
}
ngOnDestroy(): void {}
login() {
this.oidSecurityService.authorize();
console.log(this.oidSecurityService.getState);
}
logout() {
this.oidSecurityService.logoff();
}
get token() {
const claims: any = this.oidSecurityService.getToken();
return claims ? claims : null;
}
}
So when you trigger the login button the user sees the login page.
But so how to trigger directly the login page from home? So if you go to: http://localhost:4200/home user sees directly the login page
So what I have to change?
I don't have login component. I am using Identity server. So this: this.oidSecurityService.authorize(); will go to this page, where user can login:
http://localhost:4430/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dcrowd-dashboard%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520dashboard-api%26nonce%3Ddde8a3159556f497f4d3cf223540b26a1dYah1g3W%26state%3D90d1eb8c5acbe26ededcbf0a61c4e4da70sjjLw1b%26code_challenge%3DEJ1nAdtWM45Z3IoNnwVZWzAzKTz2xDC1y1c1qi1bwTU%26code_challenge_method%3DS256
You mean like this in ngOninit:
window.location.replace('http://localhost:4430/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dcrowd-dashboard%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520dashboard-api%26nonce%3D3daf0245322085adfada4bb19abb7da0c8YW1v4iG%26state%3D90d1eb8c5acbe26ededcbf0a61c4e4da70sjjLw1b%26code_challenge%3DQ-R9LMcBmSyrUCS4ZK0WljuA__z2p7S3WMXsFOjMyY0%26code_challenge_method%3DS256');
so this is my guard:
#Injectable({ providedIn: 'root' })
export class AuthorizationGuard implements CanActivate {
constructor(private oidcSecurityService: OidcSecurityService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.oidcSecurityService.isAuthenticated$.pipe(
map((isAuthorized: boolean) => {
console.log('AuthorizationGuard, canActivate isAuthorized: ' + isAuthorized);
if (!isAuthorized) {
this.router.navigate(['/unauthorized']);
return false;
}
return true;
})
);
}
}
and this is my app.routing.module.ts:
const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate: [AuthorizationGuard] },
{ path: '**', redirectTo: 'home' }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Use routers and guards as described in
https://itnext.io/handle-restricted-routes-in-angular-with-route-guards-95c93be9d05e
The Guards will instruct the routers when user can access to specific routes.
Also take a look at:
How to check: is the User logged in with angular-6-social-login npm package?
I have a module which initially redirects to
redirectTo: "/profile/bbb"
Where profile has two children :
{
path: '',
component: ProfileComponent,
children: [{
path: 'aaa',
component: AComponent
}, {
path: 'bbb',
component: BComponent
}]
}
Now - In profile's constructor I want to know what is the current route (which is profile) and what is the next route which it is goint to execute ( which is bbb).
This is the code :
profile.component.ts
constructor(private route: ActivatedRoute) {
route.children[0].url.subscribe(f => console.log(f))
}
But it shows me :
I guess I just queried the structure of the routes rather than the current active route
Question
How can I , in each path along the route , can know what is the parent route , current route , and where is it going to navigate ?
ps I don't want to do it via snapshot solution since component can be reused.
Online Demno
You can do this using ActivatedRoute.
Import it like:
import { ActivatedRoute } from '#angular/router';
Now inject it in the component:
constructor( private route: ActivatedRoute) {
console.log('Parent URL:', route.parent.url['value'][0].path);
console.log('Child URL:', route.firstChild.url['value'][0].path);
}
If you want to know complete URL for every navigation.
Then you can do this by using Router. Probably in AppComponent.
import { Router, NavigationStart, NavigationEnd } from '#angular/router';
A component will look like:
constructor(private router: Router) {
router.events.subscribe((route) => {
if (route instanceof NavigationStart) {
console.log("NavigationStart called:", route.url);
}
if (route instanceof NavigationEnd) {
console.log("NavigationEnd called:", route.url);
}
});
}
I am trying to redirect to a route when user directly paste the url.
I want to direct the user to /en/sell page on hitting the url
http://localhost:3000/en/sell/confirmation
here is my code,
ngOnInit() {
this.storedListing = this.sellerFlow.getSellerFlowObject();
if (this.storedListing === null) {
this.router.navigate(['./']);
}
}
i can see this.router getting executed but the application does not have any change. what is the issue?
You have to use ../ if you want to go from /en/sell/confirmation to /en/sell/:
this.router.navigate(['../']);
See the documentation.
You could instead redirect from your routing:
{
path: 'en/sell/confirmation',
redirectTo: 'en/sell',
pathMatch: 'full'
},
import {OnInit} from '#angular/core';
import {Router} from '#angular/router';
export class AddDisplay {
constructor(private router: Router){}
ngOnInit() {
this.router.navigate(['./SomewhereElse']);
}
}
You have to specify the relativeTo param, as below:
import { ActivatedRoute, Router } from '#angular/router';
constructor(private route: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.storedListing = this.sellerFlow.getSellerFlowObject();
if (this.storedListing === null) {
this.router.navigate(['../'], { relativeTo: this.route });
}
}
I have this code.
Route 'new' this child route for 'users'.
Route 'users' has resolver.
This work fine.
But after success create user.
I redirect to 'users', but new user not display in list, because
DataResolver not work after redirect from child route.
How Can i fix it?
//Roiting
export const ROUTES: Routes = [
{ path: 'dashboard',
component: Dashboard,
children: [
{ path: 'users',
component: Users,
resolve: {
users: DataResolver
},
children: [
{ path: 'new', component: NewUser }
]
},
]
}
];
//Resolver
#Injectable()
export class DataResolver implements Resolve<any> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
return this.userService.all(); // return users
}
}
//Component
export class NewUser {
errorMessage: string;
user: User;
constructor(public route: ActivatedRoute,
private userService: UserService,
private router: Router) {
this.user = new User();
}
onSubmit(): void {
this.userService
.createUser(this.user)
.subscribe(
user => {
this.router.navigate(['/dashboard', 'users']);
},
error => this.errorMessage = <any>error);
}
}
// USers component
export class Users implements OnInit {
users: User[];
constructor(public route: ActivatedRoute,
private router: Router) {
this.route.data.subscribe((data: any) => {
this.users = data.users;
});
}
}
Your 'Users' component should be like this, I assume you return User[] type from your web service;
export class Users {
users;
constructor(private _route: ActivatedRoute, ...){
_route.data.subscribe((wrapper: {res: any[] }) => {
this.users = <User[]>wrapper.res;
});
}
}
When your link is .../dashboard/user, it gets users via resolver and wrap it. I just call it as wrapper, you can give another name. Just know that after resolving, it wraps the response from your service.
Please let me know if you need more information.
Edit 1:
Here is how I use resolver, I hope it helps
//app.route
const appRoutes: Routes = [
{
path: '',
redirectTo: 'user',
pathMatch: 'full'
},
{
path: 'user',
loadChildren: '.../user.module#UserModule'
}
];
const rootRoutes: Routes = [
...appRoutes
];
export const appRouting = RouterModule.forRoot(rootRoutes, { useHash: true });
//user.route
const userRoutes: Routes = [
{
path: '',
component: UserComponent,
children: [
{
path: 'create',
component: UserCreateComponent
},
{
path: '',
component: UserListComponent,
resolve: {
res: UserResolver
}
}
]
}
];
export const userRouting = RouterModule.forChild(userRoutes);
//user.module
#NgModule({
imports: [
CommonModule,
ReactiveFormsModule,
userRouting,
FormsModule
],
declarations: [
UserComponent,
UserCreateComponent,
UserListComponent
],
providers: [
UserService,
UserResolver
]
})
export class UserModule { }
//user.resolver
export class UserResolver implements Resolve<any>{
constructor(private service: UserService) { }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
return this.service.get();//return all users
}
}