【问题标题】:Angular6 AutoFocus using *ngIf使用 *ngIf 的 Angular6 自动对焦
【发布时间】:2020-11-29 17:51:05
【问题描述】:
<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 对象?

编辑根据建议更新了我的代码,这仍然不会自动聚焦在 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(() =&gt; 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>

【问题讨论】:

  • 试试
  • 应该有一种方法可以使其与ngIf 一起工作,而无需setTimeout
  • @ConnorsFan 你说得对,不需要隐藏,我会更新我的帖子
  • 你也不需要setTimeout。请参阅下面的答案。

标签: angular


【解决方案1】:

借助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 检索下拉元素,并在ngAfterViewInit 中设置QueryList.changes 事件处理程序。当您被通知该元素已变为可见时,您可以将焦点设置在它上面:

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 以获取演示。

【讨论】:

  • 我需要在销毁时退订吗?
  • 根据this answer,您不必这样做。我做了一个stackblitz 表明它会自动关闭。
【解决方案2】:

*ngIf="showDropDown" 更改为[hidden]="! showDropDown",您应该能够在组件内使用@ViewChild 并防止“不受约束”的问题。

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

【讨论】:

  • 感谢您的帮助,但它仍然不会自动聚焦在 div 上
  • @gh9 在这里查看答案 > stackoverflow.com/questions/38307060/…
  • 非常感谢!有效的我也会用有效的方法更新我的帖子
  • 感谢您的帮助
  • 没问题。我将把这个答案留在这里 10 分 :)
【解决方案3】:

如果您为两个元素使用一个公共容器,并在容器上设置 focusout,则下拉菜单将在任何点击时隐藏,包括对下拉元素的点击 - 无需手动设置焦点。 (注意我们必须在父节点上设置 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;
}

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签