Misael Landeros
Misael Landeros

Reputation: 595

Function inside a function is not a function and is undefined

Overview

I'm learning Angular and JHipster, and I'm trying to get the id of an object in a collection.

I'm trying to get the id using trackBy but I getting this error:

[Error] ERROR – TypeError: this.cargarElementosFoda is not a function. (In 'this.cargarElementosFoda(item.id)', 'this.cargarElementosFoda' is undefined)

    TypeError: this.cargarElementosFoda is not a function. (In 'this.cargarElementosFoda(item.id)', 'this.cargarElementosFoda' is undefined)trackIdcheckdiffngDoCheckcheckAndUpdateDirectiveInlinedebugCheckAndUpdateNodedebugCheckDirectivesFn(función anónima)checkAndUpdateViewcallViewActionexecEmbeddedViewsActioncheckAndUpdateViewcallViewActionexecComponentViewsActioncheckAndUpdateViewcallViewActionexecEmbeddedViewsActioncheckAndUpdateViewcallViewActionexecComponentViewsActioncheckAndUpdateViewcallWithDebugContextdetectChangesforEachtick(función anónima)onInvokerunnext(función anónima)__tryOrUnsubnext_nextnextnextemitcheckStableonLeaveonInvokeTaskrunTaskinvokeTaskinvokeTaskglobalZoneAwareCallback
        error
        View_PlanEstrategicoDetailComponent_1 (PlanEstrategicoDetailComponent.ngfactory.js:337)
        logError (core.js:12446)
        (función anónima)
        handleError (core.js:1922)
        run (zone.js:137)
        tick (core.js:5374)
        (función anónima) (core.js:5210:110)
        onInvoke (core.js:4343)
        run (zone.js:137)
        next (core.js:5210:85)
        (función anónima) (core.js:3993)
        __tryOrUnsub (Subscriber.js:262)
        next (Subscriber.js:200)
        _next (Subscriber.js:138)
        next (Subscriber.js:102)
        next (Subject.js:64)
        emit (core.js:3985)
        checkStable (core.js:4312)
        onLeave (core.js:4379)
        onInvokeTask (core.js:4337)
        runTask (zone.js:187)
        invokeTask (zone.js:495)
        invokeTask (zone.js:1539)
        globalZoneAwareCallback (zone.js:1576)

I don't know why this is happening because all my other functions are working well.

This is the TS component:

      import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http';
import { JhiEventManager, JhiParseLinks, JhiAlertService } from 'ng-jhipster';

import { DiagnosticoFodaService } from 'app/entities/diagnostico-foda';
import { IPlanEstrategico } from 'app/shared/model/plan-estrategico.model';
import { IDiagnosticoFoda } from 'app/shared/model/diagnostico-foda.model';
import {IElementosDiagnosticoFoda} from 'app/shared/model/elementos-diagnostico-foda.model';
import { ElementosDiagnosticoFodaService } from 'app/entities/elementos-diagnostico-foda';
@Component({
    selector: 'sigem-plan-estrategico-detail',
    templateUrl: './plan-estrategico-detail.component.html'
})
export class PlanEstrategicoDetailComponent implements OnInit {
    planEstrategico: IPlanEstrategico; 
    diagnosticoFodas: IDiagnosticoFoda[];
    elementosDiagnosticoFodas : IElementosDiagnosticoFoda[];
    elementosFodas: IDiagnosticoFoda[];
    idPlan : number;

    constructor(
        private jhiAlertService: JhiAlertService, 
        private activatedRoute: ActivatedRoute,
        private diagnosticoFodaService: DiagnosticoFodaService,
        private elementosDiagnosticoFodaService : ElementosDiagnosticoFodaService) {}

    ngOnInit() {
        this.activatedRoute.data.subscribe(({ planEstrategico }) => {
            this.planEstrategico = planEstrategico;
            this.idPlan = planEstrategico.id; 
            this.cargarAnaliziFoda(this.idPlan);
        });

    }

    previousState() {
        window.history.back();
    }
    private onError(errorMessage: string) {
        this.jhiAlertService.error(errorMessage, null, null);
    }

    cargarAnaliziFoda(id){
        this.diagnosticoFodaService.findByPlan(id).subscribe(
            (res: HttpResponse<IDiagnosticoFoda[]>) => {
                this.diagnosticoFodas = res.body;   
            },
            (res: HttpErrorResponse) => this.onError(res.message)
        );
    }
    cargarElementosFoda(id_foda){ 
        /*this.elementosDiagnosticoFodaService.findByFODA(id_foda).subscribe(
            (res: HttpResponse<IElementosDiagnosticoFoda[]>) => {
                this.elementosDiagnosticoFodas = res.body;   
                console.log(this.elementosDiagnosticoFodas);
            },
            (res: HttpErrorResponse) => this.onError(res.message)
        );*/
    }
    trackId(index: number, item: IDiagnosticoFoda) {
        console.log('el id de este diagnostico foda es' + item.id);
        this.cargarElementosFoda(item.id); 
    }


}

And HTML component:

This is the part of the html where I call track by id

<ngb-panel  *ngFor="let diagnosticoFoda of diagnosticoFodas;trackBy: trackId">
<ng-template  ngbPanelTitle>
<span > Diagnostico FODA {{diagnosticoFoda.nombre}} 
</span>
</ng-template>

Notes

Upvotes: 2

Views: 1089

Answers (1)

Shaun Luttin
Shaun Luttin

Reputation: 141462

The Problem

My guess is that an event handler is calling the trackId method. If we call a method from an event handler, the method no longer has its this bound to an instance of the class. With the this no longer bound to an instance of the class, the cargarElementosFoda method is undefined, which is what your error states.

One Solution

Make trackId into an arrow function instead of a method. That will ensure that this is bound to an instance of the class even when the arrow function is called from an event.

trackId = (index: number, item: IDiagnosticoFoda) => {
    console.log('el id de este diagnostico foda es' + item.id);
    this.cargarElementosFoda(item.id); 
}

More Details

Here is a simplified example with one event that calls an arrow function and another event that calls a method. Note that the method has this bound to the class only when it is called from an instance of that class.

class Foo {

  someMethod() {
    console.log('someMethod:' + (this instanceof Foo));
  }

  someArrowFunction = () => {
    console.log('someArrowFunction:' + (this instanceof Foo));
  };
}

const foo = new Foo();

// when called from an instance of the class,
// both the arrow function and the method are bound to an instance of Foo
foo.someArrowFunction();
foo.someMethod();

// when not called from an event
// the arrow function remains bound to the instance of Foo
document
  .getElementById('btn1')
  .addEventListener("click", foo.someArrowFunction);

// when not called from an event
// the  method is no longer bound the instance of Foo
document
  .getElementById('btn2')
  .addEventListener("click", foo.someMethod);
<button id="btn1">Invoke Arrow Function</button>
<button id="btn2">Invoke Method</button>

Upvotes: 2

Related Questions