Search code examples
angularcontenteditableangular-componentsangular-changedetection

contentEditable.focus needs setTimeout to work when contenteditable enabled in a mat menu


this is my html:

<span #myspan [contenteditable]="editable">
...
<mat-menu #appMenu="matMenu">
  <ng-template matMenuContent>
    <button mat-menu-item (click)="setEditiable()">
      <mat-icon>edit</mat-icon>
      <span i18n>Edit</span>
    </button>
  </ng-template>
</mat-menu>

this is my ts:

setEditable(){
 this.editable = true;
 console.log(this.myspan.nativeElement.contentEditable); //false
 this.changeDetector.detectChanges();
 console.log(this.myspan.nativeElement.contentEditable); //true
 this.myspan.nativeElement.focus();
}

This code does not work, however wrapping the focus() line in a setTimeout, does. Also, if the enable button is not in a mat-menu, it also works fine without a need for a setTimeout.

Oh, I am using @ng-stack/contenteditable to enable contenteditable

stackblitz: https://stackblitz.com/edit/angular-ysb2pt


Solution

  • The reason for that is that mat-menu component restores focus to the triggering button as soon as menu is closed. This means that your focus method has no effect because it is being immediately overrided.

    Wrapping focus method in a setTimeout solves the problem since now you call focus after focus has been restored.

    Another solution is to say Angular mat-menu to not restore focus by using [matMenuTriggerRestoreFocus]="false" on trigger:

    <button mat-icon-button [mat-menu-trigger-for]="appMenu" [matMenuTriggerRestoreFocus]="false"  
    

    Forked Stackblitz