9
votes

Simple Angular 2 question: why do I get a DI (dependency injection) error when I inject RouterStateSnapshot into my constructor in my Login Component? I'm trying to get the url prior to logging out, so I can pass that in for when a user logs back in (so it'll load their last visited component/page). This is proving more difficult than I expected. Even after importing it in and including RouterStateSnapshot in my constructor, I get a DI error. This is how I've set it up in my Login Component:

import { ActivatedRoute, ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';

constructor(private router: Router,
            private route: ActivatedRoute,
            private authenticationService: AuthenticationService,
            private alertService: AlertService,
            private state: RouterStateSnapshot,
            private authGuardService: AuthGuardService,
            private idle: Idle)
{

What's the problem here? What am I missing about RouterStateSnapshot that's different than ActivatedRoute, ActivatedRouteSnapshot, etc - which I can import in and inject without problem? Why can't I inject RouterStateSnapshot in the same way?

By the way, I can use RouterStateSnapshot in my authGuardService without issue. It's being used in my canActivate() function - and returns the right result. So what's different in this situation? Why can't I use it here in my Login Component?

3

3 Answers

13
votes

I think you can get the RouterStateSnapshot from the RouterState. Consider this example:

constructor(private router: Router) {
    let routerStateSnapshot = this.router.routerState.snapshot;
}
0
votes

RouteGuardService.ts

import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router} from '@angular/router';

import {LoginService} from './login.service';

@Injectable({
  providedIn: 'root'
})
export class RouteGuardService implements CanActivate {

  constructor(private loginService: LoginService, private router: Router) {
  }

  canActivate(activatedRoute: ActivatedRouteSnapshot): boolean {
    if (this.loginService.isLoggedIn()) {
      return true;
    }
    this.router.navigate(['login'], {queryParams: {returnUrl: activatedRoute.routeConfig.path}});
    return false;
  }
}

LoginComponent.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {LoginService} from '../service/login.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  errorMessage = 'Invalid Credentials';
  invalidLogin = false;
  username = 'in28minutes';
  password = 'novell';
  returnUrl: string;

  constructor(private router: Router, public loginService: LoginService, private activatedRoute: ActivatedRoute) {
  }

  ngOnInit(): void {
  }

  handleLogin(): any {
    this.returnUrl = this.activatedRoute.snapshot.queryParams.returnUrl || `/welcome/${this.username}`;
    if (this.loginService.authenticate(this.username, this.password)) {
      this.router.navigateByUrl(this.returnUrl);
    } else {
      this.router.navigate(['login']);
      this.invalidLogin = true;
    }
  }


}

app-routing.module.ts

import {Component, NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {LoginComponent} from './login/login.component';
import {TodoListComponent} from './todo-list/todo-list.component';
import {WelcomeComponent} from './welcome/welcome.component';
import {ErrorComponent} from './error/error.component';
import {RouteGuardService} from './service/route-guard.service';
import {TodoComponent} from './todo/todo.component';

const routes: Routes = [
  {path: '', component: LoginComponent, canActivate: [RouteGuardService]},
  {path: 'login', component: LoginComponent},
  {path: 'welcome/:username', component: WelcomeComponent, canActivate: [RouteGuardService]},
  {path: 'todos', component: TodoListComponent, canActivate: [RouteGuardService]},
  {path: 'todo/:id', component: TodoComponent, canActivate: [RouteGuardService]},
  {path: '**', component: ErrorComponent}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {

}
0
votes

If you want to create returnUrl from a method/function instead of using canActivate Interface or Authguard, In the function,

constructor (
    private route: ActivatedRoute,
}

sampleFunction (){
    this.router.navigate(['/auth/login'], {
        queryParams: {
            returnUrl: this.router.routerState.snapshot.url
        }
    })
}