0

I'm trying to get a hang of routing in ng2 and I faced a strange issue. I tried to set a timeout to navigate me back to '/' when a user reaches '/home'.

This works:

export class HomeComponent implements OnInit {

    constructor(private router: Router) { }

    ngOnInit() {
        setTimeout(() => {this.router.navigate(['/']);}, 2000);
    }

}

But this does not:

export class HomeComponent implements OnInit {

    constructor(private router: Router) { }

    ngOnInit() {
        setTimeout(function () {this.router.navigate(['/']);}, 2000);
    }

}

It fails with - EXCEPTION: Cannot read property 'navigate' of undefined

To make it work, I have to change it to:

export class HomeComponent implements OnInit {

    constructor(private router: Router) { }

    ngOnInit() {
        var _router = this.router;
        setTimeout(function (_router) {_router.navigate(['/']);}, 2000, _router);
    }

}

Incidentally, this is how TypeScript compiles () => {} into. But does it not know that this is not available within setTimeout() in the second code snippet? Is this a limitation of TypeScript?

7
  • 5
    () => {} is an ECMAScript 6 Arrow Function: "An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. Arrow functions are always anonymous. These function expressions are best suited for non-method functions, and they cannot be used as constructors." The changes works because there is no reliance on this. Commented Jan 6, 2017 at 6:55
  • 1
    Arrow functions inherit this from their surrounding scope, while old-style functions don't inherit this from their surrounding scope. The difference is important because of the "this" problem with setTimeout. Commented Jan 6, 2017 at 6:57
  • I agree with both @user2864740 and -4castle in that they are concerns with the way JavaScript handles scope. But isn't TypeScript supposed to work around these? Commented Jan 6, 2017 at 6:58
  • 3
    See stackoverflow.com/questions/34361379/… Commented Jan 6, 2017 at 6:58
  • 1
    Thank you. stackoverflow.com/questions/34361379/… - this answered my query. I have voted the question be closed as a duplicate. Commented Jan 6, 2017 at 7:01

1 Answer 1

5

For Typescript, this is the Object, which represented like $scope variable in Angular 1.x. If you write native JavaScript in the Scope of Typescript logic then it will consider this as an window object. So you will not able to access typescript object this anymore.

To overcome this, I have a simple idea to be applied whenever you use JavaScript code:

export class HomeComponent implements OnInit {
   constructor(private router: Router) { }
   ngOnInit() {
      let that = this; // Assign scope variable to temporary variable: that 
      setTimeout(function () {that.router.navigate(['/']);}, 2000); // Use that particular variable anywhere in the method scope instead of Scope variable
   }
}

Note: Typescript doesn't encourage you to use JavaScript in the code. Because ts linting is already generating JavaScript output. But still if you want to use JavaScript, then this is the only solution.

Sign up to request clarification or add additional context in comments.

2 Comments

Are you saying there is a conflict of scope for this when I use function () {}? Which is why TypeScript leaves it as is?
Correct. Typescript doesn't encourage you to use JavaScript in the code. Because ts linting is already generating JavaScript output. But still if you want to use JavaScript, then this is the only solution that I found. Hope this helps. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.