81

我正在 Angular2 (Beta 8) 中开发一个组件。该组件有一个文本框和一个下拉菜单。我想在加载组件或下拉更改事件后立即在文本框中设置焦点。我将如何在 angular2 中实现这一点。以下是该组件的 Html。

<div>
    <form role="form" class="form-horizontal ">        
        <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Name</label>
                <div class="col-md-7 col-sm-7">
                    <input id="name" type="text" [(ngModel)]="person.Name" class="form-control" />

                </div>
                <div class="col-md-2 col-sm-2">
                    <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" />
                </div>
            </div>
        </div>
        <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Person</label>
                <div class="col-md-7 col-sm-7">
                    <select [(ngModel)]="SelectedPerson.Id"  (change)="PersonSelected($event.target.value)" class="form-control">
                        <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option>
                    </select>
                </div>
            </div>
        </div>        
    </form>
</div>

4

10 回答 10

82

使用简单autofocus的 HTML5 属性适​​用于“加载”场景

 <input autofocus placeholder="enter text" [(ngModel)]="test">

或者

<button autofocus (click)="submit()">Submit</button>

http://www.w3schools.com/TAgs/att_input_autofocus.asp

于 2017-02-03T04:03:27.163 回答
80

这个答案的灵感来自帖子 Angular 2: Focus on new added input element

在Angular2中将焦点设置在Html元素上的步骤

  1. 在组件中导入 ViewChildren

    import { Input, Output, AfterContentInit, ContentChild,AfterViewInit, ViewChild, ViewChildren } from 'angular2/core';
    
  2. 为要设置焦点的 html 声明本地模板变量名称

  3. 实现函数 ngAfterViewInit() 或其他适当的生命周期钩子
  4. 以下是我用于设置焦点的一段代码

    ngAfterViewInit() {vc.first.nativeElement.focus()}
    
  5. #input属性添加到要访问的 DOM 元素。

///This is typescript
import {Component, Input, Output, AfterContentInit, ContentChild,
  AfterViewChecked, AfterViewInit, ViewChild,ViewChildren} from 'angular2/core';

export class AppComponent implements AfterViewInit,AfterViewChecked { 
   @ViewChildren('input') vc;
  
   ngAfterViewInit() {            
        this.vc.first.nativeElement.focus();
    }
  
 }
<div>
    <form role="form" class="form-horizontal ">        
        <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Name</label>
                <div class="col-md-7 col-sm-7">
                    <input #input id="name" type="text" [(ngModel)]="person.Name" class="form-control" />

                </div>
                <div class="col-md-2 col-sm-2">
                    <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" />
                </div>
            </div>
        </div>
        <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Person</label>
                <div class="col-md-7 col-sm-7">
                    <select [(ngModel)]="SelectedPerson.Id"  (change)="PersonSelected($event.target.value)" class="form-control">
                        <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option>
                    </select>
                </div>
            </div>
        </div>        
    </form>
</div>

于 2016-03-04T10:07:11.783 回答
34
<input id="name" type="text" #myInput />
{{ myInput.focus() }}

这是最好和最简单的方法,因为代码“myInput.focus()”在输入创建后运行

警告:仅当表单中有单个元素时,此解决方案才可接受(用户将无法选择其他元素)

于 2018-05-17T08:51:06.730 回答
29

最初的问题要求一种方法来最初设置焦点,或者稍后设置焦点,以响应事件。似乎解决此问题的正确方法是创建一个可以为任何输入元素设置的属性指令,然后使用自定义事件安全地触发该输入元素上的焦点方法。为此,首先创建指令:

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 => {
            this.renderer.invokeElementMethod(this.element.nativeElement, 'focus', []);
        });
    }
}

请注意,它在 nativeElement 上使用 renderer.invokeElementMethod,这是 web worker 安全的。另请注意,focusEvent 被声明为输入。

然后将以下声明添加到 Angular 2 组件,该组件具有您希望使用新指令将焦点设置到输入元素的模板:

public focusSettingEventEmitter = new EventEmitter<boolean>();

ngAfterViewInit() { // ngOnInit is NOT the right lifecycle event for this.
    this.focusSettingEventEmitter.emit(true);
}
setFocus(): void {
  this.focusSettingEventEmitter.emit(true);
}

不要忘记在组件上方导入 EventEmitter,如下所示:

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

在该组件的模板中,设置新的 [focus] 属性,如下所示:

<input id="name" type="text" name="name" 
    [(ngModel)]="person.Name" class="form-control"
    [focus]="focusSettingEventEmitter">

最后,在您的模块中,像这样导入并声明新指令:

import { FocusDirective } from './focus.directive';

@NgModule({
    imports: [ BrowserModule, FormsModule ],
    declarations: [AppComponent, AnotherComponent, FocusDirective ],
    bootstrap: [ AppComponent ]
})

回顾一下:ngAfterViewInit 函数将导致新的 EventEmitter 发射,因为我们将此发射器分配给模板中输入元素中的 [focus] 属性,并且我们将此 EventEmitter 声明为新指令的输入并调用焦点在我们传递给订阅此事件的箭头函数中的方法,输入元素将在组件初始化后获得焦点,并且每当调用 setFocus 时。

我在自己的应用程序中也有同样的需求,这就像宣传的那样。非常感谢以下内容:http: //blog.thecodecampus.de/angular-2-set-focus-element/

于 2016-11-12T21:50:02.607 回答
6

有关如何设置焦点的信息,请参阅Angular 2:关注新添加的输入元素。

对于“加载”,使用ngAfterViewInit()生命周期回调。

于 2016-03-04T07:16:02.667 回答
2

我有一个稍微不同的问题。我在模态中处理输入,这让我发疯。没有任何建议的解决方案对我有用。

直到我发现这个问题:https ://github.com/valor-software/ngx-bootstrap/issues/1597

这个好人给了我提示,ngx-bootstrap modal有一个焦点配置。如果此配置未设置为 false,则模态将在动画之后聚焦,并且无法聚焦其他任何内容。

更新:

要设置此配置,请将以下属性添加到模态 div:

[config]="{focus: false}"

更新 2:

为了强制将焦点放在输入字段上,我编写了一个指令并在每个 AfterViewChecked 循环中设置焦点,只要输入字段具有 ng-untouched 类。

 ngAfterViewChecked() {
    // This dirty hack is needed to force focus on an input element of a modal.
    if (this.el.nativeElement.classList.contains('ng-untouched')) {
        this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []);
    }
}
于 2017-04-26T23:44:09.550 回答
2

此外,它可以像这样动态地完成......

<input [id]="input.id" [type]="input.type" [autofocus]="input.autofocus" />

输入在哪里

const input = {
  id: "my-input",
  type: "text",
  autofocus: true
};
于 2019-02-09T02:18:33.477 回答
2

自动对焦第一个字段的指令

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

@Directive({
  selector: "[appFocusFirstEmptyInput]"
})
export class FocusFirstEmptyInputDirective implements AfterViewInit {
  constructor(private el: ElementRef) {}
  ngAfterViewInit(): void {
    const invalidControl = this.el.nativeElement.querySelector(".ng-untouched");
    if (invalidControl) {
      invalidControl.focus();
    }
  }
}

于 2020-02-16T15:37:24.277 回答
0

我对所有浏览器上的许多这些解决方案都不太满意。这是对我有用的解决方案。

对于路由器更改:

router.events.subscribe((val) => {
    setTimeout(() => {
        if (this.searchElement) {
            this.searchElement.nativeElement.focus();
        }
    }, 1);
})

然后ngAfterViewInit()是 onload 场景。

于 2018-07-31T17:06:07.063 回答
0

你可以使用 $ (jquery) :

<div>
    <form role="form" class="form-horizontal ">        
        <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Name</label>
                <div class="col-md-7 col-sm-7">
                    <input id="txtname`enter code here`" type="text" [(ngModel)]="person.Name" class="form-control" />

                </div>
                <div class="col-md-2 col-sm-2">
                    <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" />
                </div>
            </div>
        </div>
        <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}">
            <div class="form-group">
                <label class="control-label col-md-1 col-sm-1" for="name">Person</label>
                <div class="col-md-7 col-sm-7">
                    <select [(ngModel)]="SelectedPerson.Id"  (change)="PersonSelected($event.target.value)" class="form-control">
                        <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option>
                    </select>
                </div>
            </div>
        </div>        
    </form>
</div>

然后在 ts :

    declare var $: any;

    @Component({
      selector: 'app-my-comp',
      templateUrl: './my-comp.component.html',
      styleUrls: ['./my-comp.component.css']
    })
    export class MyComponent  {

    @ViewChild('loadedComponent', { read: ElementRef, static: true }) loadedComponent: ElementRef<HTMLElement>;

    setFocus() {
    const elem = this.loadedComponent.nativeElement.querySelector('#txtname');
          $(elem).focus();
    }
    }
于 2020-02-20T08:29:24.843 回答