Focus an <input> element

2020-02-13 10:09发布

问题:

I've many input boxes in a div and I need to focus one of them programmatically.

How to do it?

It's something like:

<div>
<input type="text" name="txt1" />
<input type="text" name="txt2" />
<input type="text" name="txt3" />
<input type="text" name="txt4" />
<input type="text" name="txt5" />
<input type="text" name="txt6" />
</div>
<button (click)="selectSample()" />

selectSample() {
    ?????????('txt3').focus();
    console.log('Button pressed, txt3 has been selected');
}

回答1:

@Component({
  selector: 'my-app',
  template: `
<div>
<input #input type="text" name="txt1" />
<input #input type="text" name="txt2" />
<input #input type="text" name="txt3" />
<input #input type="text" name="txt4" />
<input #input type="text" name="txt5" />
<input #input type="text" name="txt6" />
</div>
<button (click)="selectSample()">click</button>
`
})
export class App {
  @ViewChildren('input') inputs;

  selectSample() {
    // console.debug(this.inputs.toArray().find((e) => {
    //  return e.nativeElement.getAttribute('name') == 'txt3';
    //}).nativeElement.value);

    this.inputs.toArray().find((e) => {
      return e.nativeElement.getAttribute('name') == 'txt3';
    }).nativeElement.focus();

  }
}

Plunker example



回答2:

Take a look at the ViewChild (and ViewChildren like Gunter suggests) annotations.

You can do something like this:

@Component({
  selector: 'samples',
  template: `
    <div>
      <input type="text" name="txt1">
      <input type="text" name="txt2">
      <input type="text" name="txt3" #input3>
      <input type="text" name="txt4">
      <input type="text" name="txt5">
      <input type="text" name="txt6">
    </div>
    <button (click)="selectSample()">select</button>`
})    
export class SamplesComponent {

  @ViewChild('input3') input3:ElementRef;

  constructor(private _renderer : Renderer) {}

  public selectSample() {
     //as per Eric's suggestion
     this._renderer.invokeElementMethod(this.input3.nativeElement, 'focus', []);
  }
}


回答3:

Here's a Directive implementation, per Eric's suggestion:

@Directive({selector: 'input'})
export class MyInput {
  constructor(private _elRef:ElementRef, private _renderer:Renderer) {}
  focusIf(attrValue:string) {
    console.log(this._elRef.nativeElement.getAttribute('name'))
    if(this._elRef.nativeElement.getAttribute('name') === attrValue) {
      this._renderer.invokeElementMethod(this._elRef.nativeElement, 'focus', []);
      return true;
    }
    return false;
  }
}

@Component({
  selector: 'my-app',
  directives: [MyInput],
  template: `<div>
      <input type="text" name="txt1">
      <input type="text" name="txt2">
      <input type="text" name="txt3">
      <input type="text" name="txt4">
      <input type="text" name="txt5">
      <input type="text" name="txt6">
    </div>
    <button (click)="selectSample()">click</button>`
})
export class AppComponent {
  @ViewChildren(MyInput) inputs;
  constructor() { console.clear(); }
  selectSample() {
    this.inputs.toArray().some(myInput =>
      myInput.focusIf('txt3'));
  }
}

Plunker

I like the directive approach, because we don't need to add #input to the HTML, and the directive knows how to focus itself.

I used Array.some() just to be slightly more efficient.



回答4:

My approach would be to rely on a Directive and its selector, to remove the necessity of iterating over an array, and to avoid the local variables (I don't like the idea of having too many of them on my view), as Mark mentioned.

I'm assuming that the user always want only one and it's hardcoded, which is enough for the case the user asked about. Having a dynamic element to focus would defeat this approach.

The directive

@Directive({
  selector : 'input[type=text][name=txt3]'
})
class Input {
  constructor(public renderer: Renderer, public elementRef: ElementRef) {}

  focusMe() {
    this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'focus', []);
  }
}

The component would be basically the same in each answer

export class App {
  @ViewChild(Input) input: Input;

  selectSample() {
    this.input.focusMe();
  }
}

Here's the plnkr.



标签: angular