1

I'm writing a login form in AngularJS2 and I want cursor to focus username input when the user or password return false. How can I do it?

<input type="text" class="form-control" #inputUsername placeholder="Username" autofocus ngControl="username" [(ngModel)]="username">
<input type="password" class="form-control" #inputPassword placeholder="Password" ngControl="password" [(ngModel)]="password">

this.loginService.getAuth(username, password)
  .subscribe(auth => {
    if (auth == true) {
        ????
    } else {
        ????
    }
  });
Matiratano
  • 62
  • 6

1 Answers1

3

Use a directive like explained in https://stackoverflow.com/a/34573219/217408 and modify it a bit:

@Directive({
  selector : '[focusable]'
})
class Focusable {
  constructor(public renderer: Renderer, public elementRef: ElementRef) {}

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

then use it like

<input focusable type="text" class="form-control" #inputUsername placeholder="Username" autofocus ngControl="username" [(ngModel)]="username">
<input type="password" class="form-control" #inputPassword placeholder="Password" ngControl="password" [(ngModel)]="password">

Don't forget to add it to `directives: [Focusable]

You can query for that directive like

@ViewChild(Focusable) focusable:Focusable;

...
if(auth == true) {
  ...
} else {
  this.focusable.focus();
}

Plunker example

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I got an error "Cannot read property 'focus' of undefined". This letter `this.focusable.focus();` is error – Matiratano Jun 08 '16 at 05:49
  • Are you calling `this.focusable.focus()` in the constructor? `@ViewChild()` queries are not set before `ngAfterViewInit()` is called. I added a Plunker example. – Günter Zöchbauer Jun 08 '16 at 05:55
  • May I ask you more a question? This example has only 1 selector and fix to only 1 element. How can I make it more flexible? like 'getElementById'. – Matiratano Jun 08 '16 at 06:23
  • You can add a template variable to the input and query by variable name like `` and `@ViewChild('myInput')`. You might need to add the `read` parameter like `@ViewChild('myInput', {read: Focusable})`. You can also use `@ViewChildren(Focusable) focusables:QueryList` and then iterate the list `this.focusables.toArray()...` – Günter Zöchbauer Jun 08 '16 at 06:26
  • If this fixes your issue, can you please accept the answer using the which checkmark below the up/down-vote buttons to indicate your question is answered? – Günter Zöchbauer Jun 08 '16 at 06:44
  • Of course. I have done it but they tell me I have reputation less than 15. I will do it as fast as I can. Thanks a lot. – Matiratano Jun 08 '16 at 07:00
  • Sorry, didn't know that limitation. – Günter Zöchbauer Jun 08 '16 at 07:01