Home > OS >  Cannot read properties of this object values of parent component to child component function in angu
Cannot read properties of this object values of parent component to child component function in angu

Time:08-13

I'm calling a function declared in parent component in the child component in the form of callback.

Parent Component

translation-editor.component.ts

export class TranslationEditorComponent implements OnInit {
    textGuid: string = this.actRoute.snapshot.params['textGuid'];
    editDataset: any;
    currentTopBarConfig: any;
    summaryTopbarConfig = [
      {
        "label": "Save Text",
        "function": this.save,    //see save function below
      },
      { 
        "label": "Delete Text", 
        "function": this.delete, 
      }
    ];
  constructor(
    private translationService:TranslationService,
    public actRoute: ActivatedRoute,
  ) {
  }

  ngOnInit(): void {
    this.loadDataToEdit();
  }
  loadDataToEdit(){
    this.translationService.getTextById(this.textGuid).subscribe(res => {
      this.editDataset = res;
    })
    this.currentTopBarConfig = this.summaryTopbarConfig;
  }
  save(){
    console.log("this.textGuid",this.textGuid);
    if(this.textGuid){
      this.translationService.updateText(this.textGuid, this.editDataset).subscribe((res:any)=>{
        console.log(res);
      });
    }
  }
  delete(){
 console.log("delete code lies here");
  }
}

translation-editor.component.html

<topbar [config]="currentTopBarConfig"></topbar>

<form  [ngClass]="{'hidden':currentTab!=='summary'}" >
    <fieldset>
      <legend>Field</legend>
      <ul  *ngIf="editDataset">
        <ng-container  *ngFor="let key of objectKeys(editDataset)" >
          <li *ngIf="key === 'textGuid' || key === 'strongName' || key === 'container'">
            <label >
              <input type="text" value="{{editDataset[key]}}" readonly>
              <span >{{key}}</span>
            </label>
          </li>
        </ng-container>

      </ul>
    </fieldset>

  </form>

I'm calling the save function in the below component as a callback to initiateFunction() function.

Child Component

topbar.component.html

<ul >
<ng-container *ngFor="let btn of config">
  <li>
    <button 
      (click)="initiateFunction(btn.function)"
      <span  >{{btn.label}}</span>
    </button>
  </li>
</ng-container>
</ul>

topbar.component.ts

export class TopbarComponent implements OnInit {
    @Input() config: any[] | undefined;
    constructor(private location: Location) { }
    ngOnInit(): void {
    }
    initiateFunction(fnct:any){
      fnct();
    }
  }

Here when function is executed I'm getting an error:

ERROR TypeError: Cannot read properties of undefined (reading 'textGuid')

Where I'm not able access the this.textGuid.

Please give me suggestions on how to solve this.

CodePudding user response:

I think the issue is caused because the save() function isn't bound to the correct object, so instead you can use Angular component interaction features. You can use @Output decorator and emit an event that will be handled by parent component.

First, update your TopbarComponent to add that event:

topbar.component.ts

export class TopbarComponent implements OnInit {
  @Input() config: any[] | undefined;
  @Output() save: EventEmitter<any> = new EventEmitter();
  
  constructor(private location: Location) {}
  
  ngOnInit(): void {}
  onSave() {
    this.save.emit();
    //fnct();
  }
}

topbar.component.html there was a typo on in button start tag >

<ul >
<ng-container *ngFor="let btn of config">
  <li>
    <button 
      (click)="onSave()">
      <span  >{{btn.label}}</span>
    </button>
  </li>
</ng-container>
</ul>

Next, update the TranslationEditorComponent component to bind to that event: translation-editor.component.html

<topbar [config]="currentTopBarConfig" (save)="save()"></topbar>

You can do the same for other types of events like delete or update. Refer to Angular docs for more details about components interaction and sharing data https://angular.io/guide/inputs-outputs

CodePudding user response:

Your this context has been changed when you call fnct();. In order to pass the this context to the function you can use javascript bind method. So you just need to change the config property:

summaryTopbarConfig = [
      {
        "label": "Save Text",
        "function": this.save.bind(this),    //bind current context
      }
    ];

Read more about bind: https://www.w3schools.com/js/js_function_bind.asp

  • Related