使用* ngIf的Angular6 AutoFocus

时间:2018-11-15 21:19:16

标签: angular

<div class="dropdownContainer" placeholder="test" (click)="ShowDropDown()"  />

<div #tref *ngIf="showDropDown == 1" class="dropdownList" (focusout)="HideDropDown()" style="border:1px solid black;" >this is my test</div>

单击dropDownContainer后,我希望dropdownList出现并重点关注它。

我尝试使用

  @ViewChild("tref", {read: ElementRef}) tref: ElementRef; 

方法,但是它返回undefined,因为在单击上面的div之前,该元素在DOM中不存在。如何自动聚焦于动态 NON INPUT DOM对象?

EDIT 根据建议更新了我的代码,但这仍然不会自动关注div。

  @ViewChild("tref") tref: ElementRef;
      ShowDropDown() {
      this.showDropDown = 1;
      this.tref.nativeElement.focus();
      console.log(this.tref);
  }
HideDropDown(){
  console.log('test out')
  this.showDropDown = 0;
}



<input   #tref class="dropdownContainer" placeholder="george" (click)="ShowDropDown()"  />
<div tabindex="-1" (focusout)="HideDropDown()" [hidden]="showDropDown == 0" class="dropdownList"  style="border:1px solid black;" >this is my test</div>

回答问题 有两个答案。

1)DIVS不能具有焦点,除非它们具有tabindex。 Stack answer

2)我需要包含setTimeout(() => this.tref.nativeElement.focus(), 1);,因为hidden的元素不能自动准备好接收焦点。

3)* ngIf和hidden都可以工作,一旦我完成上述修复

清理代码

import { Component,  ElementRef , ViewChild } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent {

  constructor() {
  }

  showDropDown = 0;



  @ViewChild("tref") tref: ElementRef;
  ShowDropDown() {
this.showDropDown = 1;
setTimeout(() => this.tref.nativeElement.focus(), 1);
  }

HideDropDown(){
  this.showDropDown = 0;
}

test(){ console.log('works');}

}

<div tabindex="-2"    class="dropdownContainer" placeholder="george" (click)="ShowDropDown()"   ></div>
<div tabindex="-1" #tref [hidden]="showDropDown == 0" class="dropdownList"  style="border:1px solid black;" (click)="test()" (focusout)="HideDropDown()">this is my test</div>

3 个答案:

答案 0 :(得分:3)

您可以在ViewChildrenQueryList.changes事件的帮助下,使下拉元素在可见后立即聚焦。无论元素在视图中花费多长时间,该技术都有效。

在模板中,为下拉列表tabindex赋予div属性:

<div class="dropdownContainer" (click)="showDropDown = true">
  Click here to show the dropdown
</div>

<div #dropDownDiv *ngIf="showDropDown" tabindex="1" class="dropdownList" (focusout)="showDropDown = false">
  This is the dropdown element
</div>

在代码中,使用ViewChildren检索dropdown元素,并在QueryList.changes中设置ngAfterViewInit事件处理程序。当通知您该元素已变为可见时,可以将焦点设置在该元素上:

showDropDown = false;

@ViewChildren("dropDownDiv") private dropDownDivList: QueryList<ElementRef>;

ngAfterViewInit() {
  this.dropDownDivList.changes.subscribe((list: QueryList<ElementRef>) => {
    if (list.length > 0) {
      list.first.nativeElement.focus();
    }
  });
}

有关演示,请参见this stackblitz

答案 1 :(得分:1)

*ngIf="showDropDown"更改为[hidden]="! showDropDown",您应该能够在组件内部使用@ViewChild并防止出现“未决”问题。

如果仍然不起作用,则可以始终通过将click更改为(click)="ShowDropDown(tref)"来通过click事件将元素传递给组件。请注意,为了使其正常工作,您仍然需要将* ngIf更改为[hidden]。

答案 2 :(得分:0)

如果您对这两个元素都使用了通用容器,并在容器上设置了焦点,则任何单击(包括对下拉元素的单击)都将隐藏下拉菜单-无需手动设置焦点。 (请注意,我们必须在父项上设置tabindex)。

<div class="container" (focusout)="showDropDown = false" tabindex="0">
  <div class="dropdownContainer" (click)="showDropDown = true">
    Click here to show the dropdown
  </div>

  <div #dropDownDiv *ngIf="showDropDown" tabindex="1" class="dropdownList" >
    This is the dropdown element
  </div>
</div>

css:

.container:focus {
  outline: none;
}