Knack Kwenie
Knack Kwenie

Reputation: 385

Angular 2 Material input focus not working

The inputs are inside of a modal dialog. I have no idea why it is not working. I looked at the official docs and it listed focus as something you can pass to the element but it's not working?

Does anyone know why?

Angular Material - Input Docs

<form class="example-form">

  <md-input-container class="example-full-width" style="width: 300px; padding: 5px; border-radius: 10px;">
    <input mdInput type="email" name="to" placeholder="Email">
    <md-error></md-error>
  </md-input-container>

  <md-input-container focus focused>
    <input mdInput type="text" name="a" placeholder="zzzz" focus focused (focus)="">
  </md-input-container>

</form>

Upvotes: 14

Views: 35442

Answers (7)

Sushil
Sushil

Reputation: 840

In input tag type cdkFocusInitial

<input matInput [(ngModule)]="cityName" cdkFocusInitial>

If u want more info click here

Upvotes: -1

FirstVertex
FirstVertex

Reputation: 3784

You can usually set focus without any Typescript code, using the Template markup. But in the case of a Dialog, you'll need to use @Mackelito's solution with @ViewChild and ngAfterViewInit().

I had to focus a TextArea that's inside a Menu, when that Menu appears. Fortunately, Menu has a (menuOpened) event I could bind to.

  <button mat-stroked-button color="accent" [matMenuTriggerFor]="addMenu"
    (menuOpened)="newTypes.focus()">
    Add
    <mat-icon class="dyna-dropdown-arrow">arrow_drop_down</mat-icon>
  </button>
  <mat-menu #addMenu="matMenu" [overlapTrigger]="false">
    <form [formGroup]="formGroup" (ngSubmit)="onFormSubmit()" novalidate (keydown.tab)="$event.stopPropagation()">
      <mat-form-field appearance="outline" (click)="$event.stopPropagation(); false;">
        <mat-label>New Pay Types</mat-label>
        <textarea #newTypes rows="6" matInput placeholder="New Pay Types" [formControl]="formGroup.controls['payTypes']" required></textarea>
        <mat-hint>Enter multiple Pay Types, separated by newlines</mat-hint>
        <mat-error *ngIf="formGroup.controls['payTypes'].invalid">Required</mat-error>
      </mat-form-field>
      <div fxLayout="row-reverse" fxLayoutGap="8px" fxLayoutAlign="start center">
        <button mat-stroked-button color="accent" type="submit" [disabled]="!formGroup.valid">Add</button>
        <button mat-button type="button">
          Cancel
        </button>
      </div>
    </form>
  </mat-menu>

The important part here is the (menuOpened)="newTypes.focus()" and we see the newTypes is a TemplateRef variable attached to the TextArea I want to focus marked as <textarea #newTypes.

Here's a screen shot that shows my menu opening up and it immediately gets focus to the Textarea inside it.

enter image description here

Upvotes: 0

Jayampathy Wijesena
Jayampathy Wijesena

Reputation: 1740

Have you try with cdkFocusInitial which will specify the element that will receive focus upon initialization

documentation can be found here

Upvotes: 11

Indiana
Indiana

Reputation: 333

Try to add some delay before set the input get focus. I've made this behavior a directive for your reference.

delay-focus.ts

import { Directive, Input, ElementRef } from '@angular/core';

@Directive({
  selector: '[delayFocus]'
})
export class DelayFocusDirective {

  @Input() delayFocusInterval;
  @Input() set delayFocus(condition: boolean) {
    if (condition) {
      console.log(this.delayFocusInterval);
      setTimeout(() => {
        this.el.nativeElement.focus();
      }, this.delayFocusInterval | 500);
    }
  }
  constructor(private el: ElementRef) { }
}

example

<input type="text" placeholder="Delay 100ms to get focus" delayFocus="true" delayFocusInterval="100">

You can try it here.

Upvotes: -1

Hodglem
Hodglem

Reputation: 634

I was struggling with the same issue. I was using F6 to open the dialog and I could not get the <input> to get focus. It turned out that I wasn't preventing the default behavior of F6 and F6 highlights the browser URL window; so it was stealing focus.

switch (event.keyCode) {
      case 117:
        event.preventDefault();
        this.openAddAveragesDialog();
        break;
      default:
        return;
    }

Also, no magic tag attribute works. Autofocus, Focused, Focus, whatever, no dice. I had to create a directive and use that in my input element. I got help with that using this answer.

Here is the element after adding the directive (numberOnly is another directive for only number input):

<md-input-container> <input mdInput [focus]="true" [numberOnly]="true"/></md-input-container>

**Edit : Adding Directive code as suggested by @Mackelito for clarity. Here is the directive I wrote using the answer I linked above. Keep in mind material has changed their tag labels to <input matInput> from <input md-input>

import {Directive, ElementRef, Inject, Input, OnChanges, OnInit,     Renderer} from '@angular/core';

@Directive({
  selector: '[focus]'
})

export class FocusDirective implements OnChanges, OnInit {
@Input()
focus: boolean;

constructor(@Inject(ElementRef) private element: ElementRef, public renderer: Renderer) {}

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

public ngOnChanges() {
this.element.nativeElement.focus();
}

} 

Upvotes: 6

Mackelito
Mackelito

Reputation: 4421

<form class="example-form">
  <md-input-container class="example-full-width" style="width: 300px; padding: 5px; border-radius: 10px;">
    <input mdInput #emailInput="matInput" type="email" name="to" placeholder="Email">
    <md-error></md-error>
  </md-input-container>
</form>

Then in the controller:

@ViewChild('emailInput') searchInput: MatInput;
....
ngAfterViewInit() {
  this.emailInput.focus();
}

What this.emailInput.focus() does is actually "elementRef.nativeElement.focus()" https://github.com/angular/material2/blob/master/src/lib/input/input.ts#L287

so you could do that your self like:

this.emailInput.nativeElement.focus()

Upvotes: 7

David Palita
David Palita

Reputation: 1293

Your attempts do not work because:

  • focused is a property driving the mat-focused class on mdInputContainer. You can use it to know whether your input is focused or not. You cannot use it to change the focus state.
  • focus is a method on mdInput that lets you programmatically focus the input. You can call the myInput.focus() with myInput being something like ViewChild('myInput') for instance.

But the simplest way to achieve what you want is to use the standard autofocus attribute :

<md-input-container>
    <input mdInput type="text" name="a" placeholder="zzzz" autofocus>
</md-input-container>

Upvotes: 14

Related Questions