0

I have found a lot of questions about this kind of error and I'm exhausted to find solutions that doesn't work to me... Why the "this" is undefined here on the picture?

@Component({
  ...
})
export class UsuarioCadastroComponent implements OnInit {

  usuario = new Usuario();

  mostrarBotaoResetarSenha = false;

  constructor(
    private usuarioService: UsuarioService,
    private autenticacaoService: AutenticacaoService,
    private menuService: MenuService,
    private errorHandler: ErrorHandlerService,
    private baseService: BasesService,
    private route: ActivatedRoute,
    private router: Router) { }

    ngOnInit() {
        const idUsuario = this.route.snapshot.params['id'];

        if (idUsuario) {
          this.carregarUsuario(idUsuario);
        }

        this.popularPickListBasesUsuarios();
        }

    get isEditando() {
        return Boolean(this.usuario.id);
    }

    carregarUsuario(id: number) {
        this.usuarioService.buscarPorId(id)
          .then((usuarioJson) => {
            this.usuario = usuarioJson;

            this.mostrarBotaoResetarSenha = true;

          })
          .catch(erro => this.errorHandler.handle(erro));
    }

See here the 'this' undefined

Thanks a lot!

UPDATING

At Line 62, just before the line marked by the debugger, the this is defined, as this.usuario and this.mostrarBotaoResetarSenha.

However, at line 64, these all are undefined

Guilherme
  • 143
  • 1
  • 15
  • have you define usuario varibale? – Chellappan வ Jul 19 '18 at 17:10
  • Ok. I have avoided to commit the entire code, but it is there now – Guilherme Jul 19 '18 at 17:14
  • 1
    Are you sure it's `this` that's undefined, and not the service? It's hard to tell what you're circling in the image. – Frank Modica Jul 19 '18 at 17:22
  • are you getting any error are it is just a break point? – Chellappan வ Jul 19 '18 at 17:24
  • Can you reproduce this in an [mcve] using https://stackblitz.com ? – Igor Jul 19 '18 at 17:31
  • @FrankModica, Yes, it is the this that is undefined and not the service. – Guilherme Jul 19 '18 at 17:38
  • @Gui `this` definitely should be defined since you're using an arrow function. See [this sample](https://stackblitz.com/edit/angular-this-undefined?embed=1&file=src/app/hello.component.ts) – lealceldeiro Jul 19 '18 at 17:48
  • @lealceldeiro its a closure issue having to do with the scope of execution inside the promise. I'm not familiar enough with closures myself to say more. But I my answer apparently solves the issue so... :/ – John Jul 19 '18 at 17:53
  • @John getting `this` inside `that` definitely does the trick... but this really shouldn't happen because (as I said), the OP is using an arrow function, which keeps the `this` related to the same scope. Or...Am I missing something here? – lealceldeiro Jul 19 '18 at 18:01
  • @lealceldeiro arrow functions ["retain the this value of the enclosing lexical context"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). I'm going to just assume that the promise is providing its own "lexical context" – John Jul 19 '18 at 18:10
  • Also, FWIW, I think the hold that admins put on this question is completely inappropriate. To me, the problem you are experiencing is quite clearly explained. It's also clear what you *wish were happening*. – John Jul 19 '18 at 18:12
  • Are you using bluebird? – Xiwen Li Jul 19 '18 at 18:17
  • Thanks @John... it makes sense. Do you have any handy doc where could I learn how to identify which is the _lexical context_ or the _enclosing lexical context_ of an arrow function? – lealceldeiro Jul 19 '18 at 18:43
  • @lealceldeiro I don't, sorry. And I'm just making a guess that that's what's happening here. I just duck duck go'd "javascript arrow function scope" to find the bit about lexical context. – John Jul 19 '18 at 18:56

2 Answers2

3

You could try adding this within the carregarUsuario() method closure. Something like

carregarUsuario(id: number) {
  const that = this;

  that.usuarioService.buscarPorId(id)
      .then((usuarioJson) => {
        that.usuario = usuarioJson;

        that.mostrarBotaoResetarSenha = true;

      })
      .catch(erro => that.errorHandler.handle(erro));
}

Update

Considering this worked, I'll give what little explaination I can. There are some waaaayyyy better explainations on S.O. regarding javascript closures and I'm only knowledgable enough to do some debugging myself.

Basically, the scope the promise was executing in was outside that of your component. I think the scope may have been defined by thebuscarPorId() method? Not sure. Regardless, by saving this as the local variable (that), this was brought into the same scope as the executing promise.

Put another way, this is kinda magical / special in javascript and its meaning can change. By saving this as a variable (that), you ensure it doesn't change. I'm sure some javascript expert will cringe at this explanation :). Read the post I linked to. Its better.

John
  • 9,249
  • 5
  • 44
  • 76
  • 1
    It worked for me, I can continue the work. However it still without explanation. – Guilherme Jul 19 '18 at 17:39
  • @Gui I added what little explanation I can. I only really know enough about javascript closures to do some debugging of them. Some S.O. searches will come up with *waaayyy* better explanations for you. I linked to one of them. – John Jul 19 '18 at 17:44
  • 1
    https://stackoverflow.com/a/27149227/6759854 This might be helpful – Xiwen Li Jul 19 '18 at 18:21
0

Did you define mostrarBotaoResetarSenha as a class property?

   mostrarBotaoResetarSenha = false; // add this

   ngOnInit() {
    const idUsuario = this.route.snapshot.params['id'];

    if (idUsuario) {
      this.carregarUsuario(idUsuario);
    }

    this.popularPickListBasesUsuarios();
    }

    get isEditando() {
    return Boolean(this.usuario.id);
    }

    carregarUsuario(id: number) {
    this.usuarioService.buscarPorId(id)
      .then((usuarioJson) => {
        this.usuario = usuarioJson;

        this.mostrarBotaoResetarSenha = true;

      })
      .catch(erro => this.errorHandler.handle(erro));
    }
jcroll
  • 6,875
  • 9
  • 52
  • 66