简体   繁体   English

如何将焦点设置为另一个输入?

[英]How can I set focus to another input?

I need to be able to switch focus to an input element when some event occurs. 我需要能够在发生某些事件时将焦点切换到输入元素。 How do I do that in Angular 2? 我如何在Angular 2中做到这一点?

For example: 例如:

<input (keyUp)="processKeyUp($event)"/>
<input (focusme)="alert('i am focused')"/>

I want to focus the 2nd input box when a certain key is pressed in the first. 我希望在第一个按下某个键时聚焦第二个输入框。 I think I need to use a custom event ( focusme in the snippet), but I don't know where or how to declare it, and whether to use a @Directive annotation for it, or include its definition in a component somehow. 我想我需要使用一个自定义事件( focusme在代码片段中),但我不知道在何处或如何声明它,以及是否为其使用@Directive注释,或以某种方式将其定义包含在组件中。 In short, I am stumped. 总之,我很难过。

UPDATE UPDATE

Forgot to mention, I know I can do that by using local variables in the html, but I want to be able to do it from the component, and I want to be able to do complex logic when firing the focusme event so that controls listening to it can determine if it is meant for them or not. 忘了提,我知道我可以通过在html中使用局部变量来做到这一点,但我希望能够从组件中做到这一点,并且我希望能够在触发focusme事件时执行复杂的逻辑,以便控制监听它可以确定它是否适合他们。 Thanks! 谢谢!

You can do this just passing the second input as a variable to the first one 您可以将第二个输入作为变量传递给第一个输入

For example 例如

HTML HTML

<!-- We pass focusable as a parameter to the processKeyUp function -->
<input (keyup)="processKeyUp($event, focusable)"/>

<!-- With #focusable we are creating a variable which references to the input -->
<input #focusable /> 

Later in your js/ts 后来你的js / ts

@Component({
  selector: 'plunker-app'
})
@View({
  templateUrl: 'main.html'
})
class PlunkerApp {

  constructor() {
  }

  processKeyUp(e, el) {
    if(e.keyCode == 65) { // press A
      el.focus();
    }
  }
}

el is the raw element, so you can use pure javascript on it. el是原始元素,因此您可以在其上使用纯javascript。

Here's a plnkr so you can see it working. 这是一个plnkr所以你可以看到它工作。

I hope it helps. 我希望它有所帮助。

For manipulation on DOM elements always try to use Directives. 对于DOM元素的操作总是尝试使用Directives。 In this case you are able to write simple directive. 在这种情况下,您可以编写简单的指令。

For accessing DOM from directive we can inject reference of our host DOM element by the ElementRef in directive constructor. 为了从指令访问DOM,我们可以通过指令构造函数中的ElementRef注入我们的宿主DOM元素的引用

constructor(@Inject(ElementRef) private element: ElementRef) {}

For change detection of binded value we can use ngOnChanges livecycle method. 对于绑定值的变化检测,我们可以使用ngOnChanges实时循环方法。

protected ngOnChanges() {}

All other stuff is simple. 所有其他的东西都很简单。

Simple solution 简单解决方案

// Simple 'focus' Directive
import {Directive, Input, ElementRef} from 'angular2/core';
@Directive({
    selector: '[focus]'
})
class FocusDirective {
    @Input()
    focus:boolean;
    constructor(@Inject(ElementRef) private element: ElementRef) {}
    protected ngOnChanges() {
        this.element.nativeElement.focus();
    }
}

// Usage
@Component({
    selector : 'app',
    template : `
        <input [focus]="inputFocused" type="text">
        <button (click)="moveFocus()">Move Focus</button>
    `,
    directives: [FocusDirective]
})
export class App {
    private inputFocused = false;
    moveFocus() {
        this.inputFocused = true;
        // we need this because nothing will 
        // happens on next method call, 
        // ngOnChanges in directive is only called if value is changed,
        // so we have to reset this value in async way,
        // this is ugly but works
        setTimeout(() => {this.inputFocused = false});
    }
}

Solution with EventEmitter 使用EventEmitter解决方案

To solve the problem with setTimeout(() => {this.inputFocused = false}); setTimeout解决问题(()=> {this.inputFocused = false}); We can bind our directive for events source - EventEmitter, or to Observable. 我们可以绑定我们的事件源指令 - EventEmitter,或绑定到Observable。 Below is an example of EventEmitter usage. 以下是EventEmitter用法的示例。

// Directive
import {Directive, EventEmitter, Input, ElementRef} from 'angular2/core';

@Directive({
    selector: '[focus]'
})
class FocusDirective {
    private focusEmitterSubscription;   
    // Now we expect EventEmitter as binded value
    @Input('focus')
    set focus(focusEmitter: EventEmitter) {
        if(this.focusEmitterSubscription) {
            this.focusEmitterSubscription.unsubscribe();
        }
        this.focusEmitterSubscription = focusEmitter.subscribe(
            (()=> this.element.nativeElement.focus()).bind(this))
    }    
    constructor(@Inject(ElementRef) private element: ElementRef) {}
}

// Usage
@Component({
    selector : 'app',
    template : `
        <input [focus]="inputFocused" type="text">
        <button (click)="moveFocus()">Move Focus</button>
    `,
    directives: [FocusDirective]
})
class App {
    private inputFocused = new EventEmitter();
    moveFocus() {
        this.inputFocused.emit(null);    
    }
}

Both solutions solves your problem, but second has a little better performance and looks nicer. 这两种解决方案都可以解决您的问题,但其次是性能更好,看起来更好。

Actually you don't need to write any TS code for that (I'm using one of the other answer's example): 实际上你不需要为此编写任何TS代码(我正在使用另一个答案的例子):

<input (keyup.enter)="focusable.focus()"/>
<input #focusable /> 

Set focus - Angular 2/5 设置焦点 - Angular 2/5

<input type="text" [(ngModel)]="term2" #inputBox>

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

@Component({
  selector: 'app-general',
  templateUrl: './general.component.html',
  styleUrls: ['./general.component.scss']
})
export class GeneralComponent {

  @ViewChild("inputBox") _el: ElementRef;

  setFocus() {
    this._el.nativeElement.focus();
  }
}

For setting focus on load 用于设置对负载的关注

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

You can update this logic accordingly for key press. 您可以相应地更新此逻辑以进行按键操作。

More Info 更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM