如何将焦点设置到另一个输入?
Posted
技术标签:
【中文标题】如何将焦点设置到另一个输入?【英文标题】:How can I set focus to another input? 【发布时间】:2015-10-13 10:46:24 【问题描述】:当某些事件发生时,我需要能够将焦点切换到输入元素。我如何在 Angular 2 中做到这一点?
例如:
<input (keyUp)="processKeyUp($event)"/>
<input (focusme)="alert('i am focused')"/>
我想在第一个按下某个键时聚焦第二个输入框。我想我需要使用自定义事件(sn-p 中的focusme
),但我不知道在哪里或如何声明它,以及是否为其使用@Directive
注释,或者将其定义包含在不知何故的一个组件。总之,我被难住了。
更新
忘了提,我知道我可以通过在 html 中使用局部变量来做到这一点,但我希望能够从组件中做到这一点,并且我希望能够在触发 focusme
时执行复杂的逻辑事件,以便监听它的控件可以确定它是否适合他们。
谢谢!
【问题讨论】:
你不能只用自定义事件来扩展输入元素,你需要创建自己的自定义元素来包装一个可以触发 focusme 事件的输入控件,即您可以将第二个输入作为变量传递给第一个
例如
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 />
稍后在你的 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 是原始元素,因此您可以在其上使用纯 javascript。
这是plnkr,您可以看到它的工作原理。
希望对你有帮助。
【讨论】:
感谢您的回答,但我需要将焦点传递给另一个组件中的输入元素,因此一个组件触发事件,另一个组件作用于事件并将焦点设置为输入元素在里面。 你可以同时阅读这个帖子github.com/angular/angular/issues/3186 @AviadP.,如果您想要组件间通信,并且您的组件不是“相关的”(即没有祖先或后代模式),您可以将 EventEmitter 放入服务中,将服务注入两个组件,让一个组件触发事件,并让另一个组件(您要关注的那个)订阅它。这是an example。 由于某种原因,这个答案对我不起作用(在我的代码中使用 rc.3)。我还需要关注组件代码中的元素,而不仅仅是从 DOM 触发的事件,所以 the accepted answer from here 正是我所需要的。注意更新。他们有有用的提示。 在输入(反应形式)和 cleaveJS 中的验证非常有用【参考方案2】:对于 DOM 元素的操作,请始终尝试使用指令。在这种情况下,您可以编写简单的指令。
为了从指令中访问 DOM,我们可以通过指令构造函数中的 ElementRef 注入宿主 DOM 元素的引用。
constructor(@Inject(ElementRef) private element: ElementRef)
对于绑定值的变化检测,我们可以使用 ngOnChanges livecycle 方法。
protected ngOnChanges()
所有其他的东西都很简单。
简单的解决方案
// 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);
EventEmitter 的解决方案
为了解决 setTimeout(() => this.inputFocused = false); 的问题,我们可以将我们的指令绑定到事件源 - EventEmitter 或 Observable。下面是 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);
两种解决方案都可以解决您的问题,但第二种解决方案的性能要好一些,而且看起来更好。
【讨论】:
这个答案看起来与my recent answer 惊人地相似——有点太相似了,我想说。我建议你再看看我的回答。更新 2 和 3 提供了额外的实现(我更喜欢)。 对不起,马克我没有注意到你在评论中的回答。第一个解决方案与您的条目完全相同。我也喜欢您使用@ViewChild 的解决方案,但在某些情况下(例如嵌套未知组件)指令/事件发射器解决方案更灵活。取决于用例,我会看到每个解决方案的空间。 值得注意的是,任何订阅 observables 的指令都应该是一个好公民,并在ngOnDestroy
生命周期钩子中取消订阅。【参考方案3】:
实际上您不需要为此编写任何 TS 代码(我正在使用其他答案的示例之一):
<input (keyup.enter)="focusable.focus()"/>
<input #focusable />
【讨论】:
【参考方案4】:设置焦点 - 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();
用于设置负载重点
ngAfterViewInit()
this._el.nativeElement.focus();
您可以为按键相应地更新此逻辑。
More Info
【讨论】:
以上是关于如何将焦点设置到另一个输入?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UIToolbar 完成按钮中将焦点从一个 UIButton 设置到另一个 UIButton
在 Windows 中使用 Java 将焦点设置到非 Java 应用程序