3

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?

Simonxca
  • 648
  • 1
  • 6
  • 18
  • I think you can do that by using two router outlets in the same template this way you switch between the two different component without changing the route. can you create a plunker with your current code so I can try it? – Hamed Baatour May 24 '17 at 21:19
  • I don't want to use 2 router outlets though. I was hoping angular had a flag or something for doing this that I'm not aware of. – Simonxca May 24 '17 at 22:28
  • I think your answer is here [a link](https://stackoverflow.com/questions/41928727/angular-2-different-components-with-same-route) https://stackoverflow.com/questions/41928727/angular-2-different-components-with-same-route – Luke Li Dec 19 '18 at 18:48

1 Answers1

3

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: