2

I want to reference the keyword "this" in a typescript class in my Angular project. But it cannot be used. I always get the error that the variable I want to change is not defined. Here is my implementation:

export class ContactComponent implements OnInit {
  contactForm: FormGroup;
  errorMsg:string = '';
  redirect = "";

  loggedIn(): void {
         this.redirect = "dashboard";
         console.log("success");

in my HTML the redirect variable is connected to a routerLink like this:

<a [routerLink]="redirect"></a>

I have tried this with other variables in other functions but had always the same error.

EDIT:

The loggedIn function is called within another function as "success" parameter like this:

submitForm(): void {
    DBEventProxy.instance().dbevent.login(this.contactForm['username'], 
    this.contactForm['password'], this.loggedIn, this.failed);
  }

The login function needs the parameters username, password, success function, failfunction.

Boerne
  • 149
  • 1
  • 16

3 Answers3

6

You need to bind loggedIn to the correct context. There are several options:

1) define loggedIn as bound function:

export class ContactComponent implements OnInit {
  loggedIn = () = > {
         this.redirect = "dashboard";
         console.log("success");`

2) use bind

export class ContactComponent implements OnInit {
  contactForm: FormGroup;
  errorMsg:string = '';
  redirect = "";

  loggedIn(): void {
         this.redirect = "dashboard";
         console.log("success");

    submitForm(): void {
        DBEventProxy.instance().dbevent.login(this.contactForm['username'], 
        this.contactForm['password'], this.loggedIn.bind(this), this.failed);
                                                    ^^^^^^^^^^
      }

3) wrap this.loggedIn into an arrow function that preserves context like this:

this.contactForm['password'], () => this.loggedIn(), this.failed);

And probably you want to do the same for this.failed. Read more about bind and arrow functions here

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
2

Since you're using Typescript, you can use arrow functions to preserve the context you expect (this will refer to what you want).

In SubmitForm(), replace this.loggedIn with ()=>this.loggedIn(). The same change should be made to this.failed if that's a function.

DBEventProxy.instance().dbevent.login(
    this.contactForm['username'], 
    this.contactForm['password'], 
    ()=>this.loggedIn(), 
    ()=>this.failed()
);

See the Typescript wiki

Red flags for this

The biggest red flag you can keep in mind is the use of a class method without immediately invoking it. Any time you see a class method being referenced without being invoked as part of that same expression, this might be incorrect.

Community
  • 1
  • 1
BeetleJuice
  • 39,516
  • 19
  • 105
  • 165
  • This is not the right solution for my project. When I am changing the this.loggedIn to this.loggedIn() the main function dbevent.login() does not work properly. The incoming JSON messages cannot be read and the login does not work. The bind function works fine! – Boerne Jun 25 '17 at 02:28
  • The this.loggedIn is just a reference of the function as the success parameter of the main function. If I write this.loggedIn() the function will be executed immediately, which is not what I want. – Boerne Jun 25 '17 at 02:30
  • You misread my answer. I didn't ask you to replace with `this.loggedIn()`. I wrote `()=>this.loggedIn()` – BeetleJuice Jun 25 '17 at 02:31
  • @Boerne, what errors did you get with using `.bind`? I want to understand why `bind` didn't work. Effectively `bind` returns the new function that calls `this.loggedIn` inside through apply, this is almost the same as what `()=>this.loggedIn()` does – Max Koretskyi Jun 25 '17 at 05:53
  • @Maximus there are no errors within your solution. But if it was impolite to change the 'right' answer I am sorry. But all the given answers were correct and so I thought it was the best to mark the most elegant one (my opinion). – Boerne Jun 26 '17 at 11:14
  • @Boerne, ah, sure, no problem. You wrote _this is not the right solution for my project._ - so I thought there was an error. I added another solution which I think is the most elegant :). Check my updated answer for the first option – Max Koretskyi Jun 26 '17 at 12:34
1

Instead of just referencing the function, you need to bind this to it: this.loggedIn.bind(this).
Only referencing the function ' strips ' it off the this reference it has when referencing. This is standard Javascript behavior.

Sebastian
  • 5,177
  • 4
  • 30
  • 47