Simonxca
Simonxca

Reputation: 678

Angular 2 router CanActivate how to redirect to 404 but still show the url being visited

Here's my scenario:

A user visits a route called /protected. In my CanActivate guard, I check whether the user is logged in. If they are not logged in, I want to render my 404 route, but still show /protected in the address bar. I want users to be unable to distinguish a protected page from a non-existent page.

This is what I tried and does not work.

@Injectable()
export class LoggedInGuard implements CanActivate {
  constructor(private router: Router, private userService: UserService) {}

  canActivate() {
    if (this.userService.getUser()) return true;

    this.router.navigate(['/404']);
    return false;
  }
}

After routing, the url in the address bar will show /404, but I want it to show /protected.

Changing to this.router.navigate(['/404'], { skipLocationChange: true }); also does not work because the url in the address bar will be the previous url, not /protected.

My question is: how do you render a different component if the user is not logged in while still keeping the url that they were trying to visit in the address bar?

Upvotes: 3

Views: 3280

Answers (1)

LarryBattle
LarryBattle

Reputation: 46

Problem:

The /protected route should render the error component if the user isn't logged in, else render a different component.

Possible Solution:

Define a route and component for /protected, /error, and /page1. When the user lands on /protected, navigate to /error if they're not logged in, else /page1.

Be sure to pass { skipLocationChange: true } as the second argument to router to avoid the url from navigating away from /protected.

this.router.navigate([this.url], { skipLocationChange: true });

Note:

Adding a CanActivate() check for /protected determines if you can access the path or not. So it isn't useful in this case because you want to the path to be open but show different content.

Demo:

https://plnkr.co/edit/6o2DPXmYfNiQEW2Kbr8A?p=preview

Sample code

@Component({
selector: 'app-protected',
template: `
    Location: {{href}} <br>
    Checking Login state ...
    <div *ngIf="url">Switching to {{url}}</div>
`,
})
export class AppProtected implements OnInit {
    url : string;
    href = window.location.href;

    constructor(private router : Router ) {
    }
    ngOnInit(){
        const isUserLoggedIn = /true/.test(localStorage.getItem('isUserLoggedIn'));
        this.url = isUserLoggedIn ? '/page1' : '/error';
        window.setTimeout(() => {
            this.router.navigate([this.url], { skipLocationChange: true });
        }, 2000);

    }
}

More info:

Upvotes: 3

Related Questions