Angular 5集合关注输入元素

时间:2018-04-24 16:40:31

标签: angular angular5 angular-forms

我正在使用Angular 5进行前端应用程序,我需要隐藏一个搜索框,但点击一个按钮,搜索框将显示并设置为焦点。

我已尝试使用指令左右的stackoverflow中找到的几种方法,但没有财富。

以下是示例代码:

@Component({
   selector: 'my-app',
   template: `
    <div>
    <h2>Hello</h2>
    </div>
    <button (click) ="showSearch()">Show Search</button>
    <p></p>
    <form>
      <div >
        <input *ngIf="show" #search type="text"  />            
      </div>
    </form>
    `,
  })
  export class App implements AfterViewInit {
  @ViewChild('search') searchElement: ElementRef;

  show: false;
  name:string;
  constructor() {    
  }


  showSearch(){
    this.show = !this.show;    
    this.searchElement.nativeElement.focus();
    alert("focus");
  }

  ngAfterViewInit() {
    this.firstNameElement.nativeElement.focus();
  }

搜索框未设置为焦点。 我怎样才能做到这一点?感谢。

12 个答案:

答案 0 :(得分:31)

像这样修改show search方法

showSearch(){
  this.show = !this.show;  
  setTimeout(()=>{ // this will make the execution after the above boolean has changed
    this.searchElement.nativeElement.focus();
  },0);  
}

答案 1 :(得分:11)

您应该为此使用html 自动对焦

<input *ngIf="show" #search type="text" autofocus /> 

注意:如果您的组件被保留并重新使用,则它将仅在第一次创建片段时自动聚焦。可以通过使用全局dom侦听器来克服此问题,该侦听器在连接dom片段时检查dom片段内的autofocus属性,然后重新应用它或通过javascript进行聚焦。

答案 2 :(得分:6)

在Angular中,您可以在HTML本身内将焦点设置为单击按钮时输入。

<button (click)="myInput.focus()">Click Me</button>

<input #myInput></input>

答案 3 :(得分:5)

此伪指令将立即显示并在元素中选择任何文本。在某些情况下,这可能需要setTimeout,尚未经过大量测试。

import { Directive, ElementRef, OnInit } from '@angular/core';

@Directive({
  selector: '[appPrefixFocusAndSelect]',
})
export class FocusOnShowDirective implements OnInit {

  constructor(private el: ElementRef) {
    if (!el.nativeElement['focus']) {
      throw new Error('Element does not accept focus.');
    }
  }

  ngOnInit(): void {
    const input: HTMLInputElement = this.el.nativeElement as HTMLInputElement;
    input.focus();
    input.select();
  }
}

在HTML中:

 <mat-form-field>
     <input matInput type="text" appPrefixFocusAndSelect [value]="'etc'">
 </mat-form-field>

答案 4 :(得分:3)

还有一个名为cdkFocusInitial的DOM属性,它对输入有效。 您可以在这里了解更多信息:https://material.angular.io/cdk/a11y/overview

答案 5 :(得分:2)

要在布尔值更改后执行并避免使用超时,可以执行以下操作:

import { ChangeDetectorRef } from '@angular/core';

constructor(private cd: ChangeDetectorRef) {}

showSearch(){
  this.show = !this.show;  
  this.cd.detectChanges();
  this.searchElement.nativeElement.focus();
}

答案 6 :(得分:1)

我要权衡一下(Angular 7解决方案)

  

输入[appFocus] =“ focus”。...

import {AfterViewInit, Directive, ElementRef, Input,} from '@angular/core';

@Directive({
  selector: 'input[appFocus]',
})
export class FocusDirective implements AfterViewInit {

  @Input('appFocus')
  private focused: boolean = false;

  constructor(public element: ElementRef<HTMLElement>) {
  }

  ngAfterViewInit(): void {
    // ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
    if (this.focused) {
      setTimeout(() => this.element.nativeElement.focus(), 0);
    }
  }
}

答案 7 :(得分:1)

仅使用角度模板

<input type="text" #searchText>

<span (click)="searchText.focus()">clear</span>

答案 8 :(得分:1)

我有相同的情况,这对我有用,但是我没有您拥有的“隐藏/显示”功能。因此,也许您可​​以先检查在始终可见的字段时是否获得焦点,然后尝试解决更改可见性时为何不起作用的原因(可能就是为什么需要施加睡眠或承诺)

要设置焦点,这是您唯一需要做的更改:

您的HTML垫输入应为:

<input #yourControlName matInput>

在您的TS类中,在变量部分(

export class blabla...
    @ViewChild("yourControlName") yourControl : ElementRef;

您的按钮很好,请致电:

  showSearch(){
       ///blabla... then finally:
       this.yourControl.nativeElement.focus();
}

就是这样。 您可以在我发现的这篇文章中查看此解决方案,因此感谢-> https://codeburst.io/focusing-on-form-elements-the-angular-way-e9a78725c04f

答案 9 :(得分:0)

这在没有setTimeout的Angular 8中可以正常工作:

import {AfterContentChecked, Directive, ElementRef} from '@angular/core';

@Directive({
  selector: 'input[inputAutoFocus]'
})
export class InputFocusDirective implements AfterContentChecked {
  constructor(private element: ElementRef<HTMLInputElement>) {}

  ngAfterContentChecked(): void {
    this.element.nativeElement.focus();
  }
}

说明: 好的,这是由于以下原因而起作用:更改检测。这与setTimout起作用的原因相同,但是在Angular中运行setTimeout时,它将绕过Zone.js并再次运行所有检查,并且它起作用,因为setTimeout完成时所有更改都已完成。使用正确的生命周期挂钩(AfterContentChecked),可以达到相同的结果,但优点是不会运行额外的周期。当检查并通过所有更改后,该函数将触发,并在AfterContentInit和DoCheck钩子之后运行。如果我错了,请纠正我。

https://angular.io/guide/lifecycle-hooks上有多个生命周期和变更检测

答案 10 :(得分:0)

组件的

html:

<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">

组件的控制器:

showSearch() {
  this.show = !this.show;    
}

..并且不要忘记从A11yModule导入@angular/cdk/a11y

import { A11yModule } from '@angular/cdk/a11y'

答案 11 :(得分:-1)

更简单的方法也是这样做。

let elementReference = document.querySelector('<your css, #id selector>');
    if (elementReference instanceof HTMLElement) {
        elementReference.focus();
    }