Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

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. In short, I am stumped.

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. Thanks!

like image 518
Aviad P. Avatar asked Jul 23 '15 08:07

Aviad P.


People also ask

How can you specify focus in an input field?

To set focus to an HTML form element, the focus() method of JavaScript can be used. To do so, call this method on an object of the element that is to be focused, as shown in the example. Example 1: The focus() method is set to the input tag when user clicks on Focus button.

How do you set focus to input field in React?

To set focus on an input field after rendering with React, we can assign a ref to the input element with the useRef hook. Then we call focus on the current value of the ref to focus on the input. to call useRef to create a ref and assign it to inputReference . Then we call inputReference.


2 Answers

You can do this just passing the second input as a variable to the first one

For example

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

@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.

Here's a plnkr so you can see it working.

I hope it helps.

like image 90
Eric Martinez Avatar answered Sep 17 '22 15:09

Eric Martinez


For manipulation on DOM elements always try to use 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.

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

For change detection of binded value we can use ngOnChanges livecycle method.

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

To solve the problem with setTimeout(() => {this.inputFocused = false}); We can bind our directive for events source - EventEmitter, or to Observable. Below is an example of EventEmitter usage.

// 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.

like image 37
majo Avatar answered Sep 18 '22 15:09

majo