One mistake I occasionally make as a Java or C# developer is using the this keyword. It's a moving target.

The following code console.log(this.title) prints 'Edit Dialog Title' instead of 'Main Title', what I intended.

export class MainComponent {
  title = 'Main Title';

  constructor(private readonly dialog: MatDialog) {
  }

  onClick(): void {
    console.log(this.title);
  }

  async showEditDialog() {
    const dialogRef = this.dialog.open(EditDialogComponent);
    const dialog = dialogRef.componentInstance;

    dialog.registerOnClick(this.onClick);

    const result = await dialogRef.afterClosed().toPromise();
  }
}

export class EditDialogComponent {
  title = 'Edit Dialog Title';

  private onClickHandler: () => any;

  registerOnClick(fn: any): void {
    this.onClickHandler = fn;
  }

  onClick(): void {
    this.onClickHandler();
  }
}
 

The problem is the scope during excecution of the function. this uses the caller's scope, which is that of EditDialogComponent. What I wanted was the scopt of MainComponent.

Solution

The working solution is using the lambda syntax.

  onClick = () => {
    console.log(this.title);
  }
 

An alternative is using Function.bind:

dialog.registerOnNewClick(this.onClick.bind(this));