在 ngbootstrap 弹出窗口的输入中设置焦点

Set focus in input of ngbootstrap popover

我正在使用 ng-bootstrap 弹出窗口对 table 进行过滤。基于列中数据的类型(整数、字符串、日期、..),我想显示不同类型的过滤选项。这按预期工作,但我还希望在显示弹出窗口时聚焦相应的输入字段。

ng-boostrap popover 公开了一个名为(显示)的输出,我试图使用它来调用一个函数来聚焦我的输入,这似乎不起作用。

如果我从 ngAfterViewChecked() 调用相同的函数,它会按预期进行聚焦,但是由于这个函数被调用了很多次,它似乎不是一个很好的解决方案(在我自己的网站上它被调用了大约 150 次每次切换弹出框)。我不确定为什么它会被调用这么多次,但这不是问题的重点。

我创建了一个 plunker 来显示我的问题: http://plnkr.co/edit/fr0nI1GiRT22UWXaNZwJ?p=preview

Html:

<div style="display:flex; align-items:center; justify-content:center"><button type="button" class="btn btn-outline-secondary" placement="bottom"
        [ngbPopover]="popContent" popoverTitle="Popover on bottom" (shown)="selectInput()" container="body"  triggers="manual" #p="ngbPopover" (click)="p.toggle()">
  Popover on bottom
</button>
</div>

<ng-template #popContent>
  <div class="filter-popover">
    <div>
      <label for="filterbox">Filter: </label>
      <input id="filterbox" [(ngModel)]="appliedFilter" class="form-control form-control-sm" [focus]="focusSettingEventEmitter" />
    </div>
    <div class="popover__controls d-flex justify-content-end">
      <button class="btn btn-sm btn-success" (click)="p.close()">OK</button>
      <button class="btn btn-sm btn-danger" (click)="p.close()">Cancel</button>
    </div>
  </div>
</ng-template>

组件:

import { Component, Input, Output, OnChanges, EventEmitter, HostListener, ViewChild, ViewChildren, AfterViewInit, AfterViewChecked } from '@angular/core';

@Component({
  selector: 'ngbd-popover-basic',
  templateUrl: 'src/popover-basic.html'
})
export class NgbdPopoverBasic implements AfterViewChecked {
      public focusSettingEventEmitter = new EventEmitter<boolean>();

    selectInput() {
        this.focusSettingEventEmitter.emit(true);
    }
    ngAfterViewChecked() {
      //if i call it here it will focus it, but this function is run 150 times on my site (here around 3), so we dont want to do that
      //this.selectInput();
      //console.log("checked")
    }
}

指令:

import { Directive, Input, EventEmitter, ElementRef, Renderer, Inject } from '@angular/core';

@Directive({
    selector: '[focus]'
})
export class FocusDirective {
    @Input('focus') focusEvent: EventEmitter<boolean>;

    constructor( @Inject(ElementRef) private element: ElementRef, private renderer: Renderer) {
    }

    ngOnInit() {
        this.focusEvent.subscribe((event:any) => {
            this.renderer.invokeElementMethod(this.element.nativeElement, 'focus', []);
        });
    }
}

根据我读到的其他用户关于聚焦输入的说法,您应该在 AfterViewInit 函数中执行此操作,但这对我不适用,因为组件在页面加载时被初始化,而我想要弹出窗口为 displayed/shown

时发生焦点

希望能帮我指明正确的方向

我看到您尝试使用 AfterViewChecked。是的,它会被触发 +150 次,但如果你设置条件则不会:

start;

....    
ngAfterViewChecked() {
  if(this.start){
     this.selectInput();
     console.log("checked");
     this.start = false;
  }
}   

并仅在单击弹出窗口切换按钮时将开始设置为真:

  <button ...(click)="start = true; p.toggle()">

现在在演示控制台中检查它,它仅在需要时触发并且焦点有效。

DEMO