Angular2 - 将文本框聚焦在组件加载上

par*_*rag 68 angular2-forms angular2-template angular

我正在开发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>
Run Code Online (Sandbox Code Playgroud)

小智 68

使用简单的autofocusHTML5属性适用于"加载"方案

 <input autofocus placeholder="enter text" [(ngModel)]="test">
Run Code Online (Sandbox Code Playgroud)

要么

<button autofocus (click)="submit()">Submit</button>
Run Code Online (Sandbox Code Playgroud)

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

  • 只有刷新页面或从头开始加载页面时,这似乎才有效.如果通过路由器导航到表单组件,则不会选择该字段. (38认同)
  • 当我们有多个组件时,这不是一个好的解决方案,这只适用于第一个默认组件 (3认同)

par*_*rag 65

这个答案的灵感来自后 角色2:专注于新添加的输入元素

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

  1. 在Component中导入ViewChildren

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

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

    ngAfterViewInit() {vc.first.nativeElement.focus()}
    
    Run Code Online (Sandbox Code Playgroud)
  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();
    }
  
 }
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 很简单,但是如果你需要在另一个组件中设置焦点会发生什么?例如,子组件的默认搜索框(在标题中). (2认同)
  • 动态生成的元素怎么样? (2认同)

Ken*_*gel 27

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

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', []);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

import { Component, EventEmitter } from '@angular/core';
Run Code Online (Sandbox Code Playgroud)

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

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

最后,在您的模块中,导入并声明新指令,如下所示:

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

@NgModule({
    imports: [ BrowserModule, FormsModule ],
    declarations: [AppComponent, AnotherComponent, FocusDirective ],
    bootstrap: [ AppComponent ]
})
Run Code Online (Sandbox Code Playgroud)

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

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

  • @KentWeigel-这是一个非常经典的解决方案,效果很好。这是imo的“正确”答案。谢谢。 (2认同)

Ser*_*rin 23

<input id="name" type="text" #myInput />
{{ myInput.focus() }}
Run Code Online (Sandbox Code Playgroud)

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

  • 哈哈,实际上工作!有点hacky但非常简单和功能,谢谢!:) (3认同)
  • 我一开始很喜欢它,但似乎总是让我不能选择其他元素(甚至突出显示要复制的文本).不得不切换到这里与视图儿童接受的答案. (3认同)
  • 是的,如果屏幕上只有一个编辑,这个方法是可以接受的.它可以防止将注意力集中在任何其他输入上! (3认同)
  • 隐藏的宝石!!:) 你震撼了我的朋友! (2认同)

Gün*_*uer 6

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

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