如何将焦点设置到最近的兄弟元素(如果存在)或 angular 12 中的父元素

How to set focus to the nearest sibling (if exist) or parent element in angular 12

我一直在努力寻找解决我的任务的方法 - 当我从属于评论的附件对象列表中删除附件时,我想将焦点设置到数组中剩下的最近的附件 - 如果数组为空,我想将焦点设置到父评论组件

子编辑评论html文件

<div *ngFor="let attachment of comment?.attachments; let index = index">
   <h4>{{ attachment.filename }}</h4>
   <Button [attr.id]="'remove-btn-' + index" (click)="deleteAttachment(attachment)">Remove attachment</Button>
</div>

子编辑-注释ts文件

export class EditCommentComponent {
  @Input() comment: Comment;
  @Output() deleteCommentAttachment = new EventEmitter<CommentAttachment>();

  public deleteAttachment(attachment: CommentAttachment): void {
    this.deleteCommentAttachment.emit(attachment);
}

家长列表-评论html文件

<app-edit-comment
  [comment]="comment"
  (deleteCommentAttachment)="deleteCommentAttachment($event)"
></app-edit-comment>

父列表-注释 ts 文件

export class ListCommentsComponent {
   public comment: Comment;
   // validationProtocolP - this is a variable holding all the mock data for 
                            comments

   public deleteCommentAttachment(attachment: CommentAttachment): void {
   // logic for deleting comment attachment
   // logic to set focus -
   const attachmentIndex = this.validationProtocolP.comments[commentIndex].attachments.findIndex((at) => at.id === this.attachment.id);

   if (this.comment.attachments[attachmentIndex - 1]) {
          setTimeout(() =>
            this.setFocus(document.getElementById('remove-att-btn-' + (attachmentIndex - 1))),
          );
        } else if (this.comment.attachments[attachmentIndex + 1]) {
          setTimeout(() =>
            this.setFocus(document.getElementById('remove-att-btn-' + attachmentIndex)),
          );
        } else {
          console.log('Focus set to parent of attachments');
        }


  public setFocus(el: HTMLElement): void {
    const focusElement = (el.previousSibling as HTMLElement) || (el.nextSibling as HTMLElement);
    if (focusElement) {
      focusElement.focus();
    }
  }
}

您可以传递对 DOM 元素的引用并使用 nextSiblingpreviousSibling 来聚焦这些元素。

这是基本原理的一个例子(https://stackblitz.com/edit/angular-ivy-wkwgsl?file=src/app/app.component.ts)。你可以适应你的特定逻辑:

@Component({
  selector: 'my-child',
  template: `<div><button (click)="remove.emit()">{{ comment }}</button></div>`,
})
export class ChildComponent {
  @Input() comment: string;
  @Output() remove = new EventEmitter();
}

@Component({
  selector: 'my-app',
  template: `
  <div #parent>
    <div #child *ngFor="let c of children; let index = index">
      <my-child [comment]="c" (remove)="remove(index, child, parent)"></my-child>
    </div>
  </div>`,
})
export class AppComponent {
  children = ['1', '2', '3'];

  remove(index: number, child: HTMLElement, parent: HTMLElement) {
    this.children.splice(index, 1);
    const focusElement =
      (child.previousSibling as HTMLElement) ||
      (child.nextSibling as HTMLElement) ||
      parent;
    if (focusElement && typeof focusElement.focus === 'function') {
      focusElement.focus();
    }
  }
}