14

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>
Kuldeep Bhimte
  • 961
  • 1
  • 10
  • 25
Knack Kwenie
  • 377
  • 2
  • 4
  • 20
  • Can you better describe the problem? Can't you compile the code? Crashes it when you run it? Does it behave differently than expected? What's the error message? What the expected behavior? What's the effective behavior? – Codo Apr 19 '17 at 21:10
  • Looks like you have to use `focused="true"` – Edric Apr 24 '17 at 14:21

7 Answers7

14

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>
David Palita
  • 1,193
  • 9
  • 12
  • 13
    Keep in mind, `autofocus` only works when the page first loads. For our app, we're compiling and injecting a window when a user adds a new "item". `autofocus` only seems to work the first time the user attempts to add an item, but does nothing thereafter. Just something keep in mind. – kbpontius Nov 30 '17 at 20:30
  • I've noticed sometimes other elements will "steal" focus after the page has loaded. For example, my seems to take focus regardless of an autofocus on another element. – Jus10 Feb 19 '18 at 18:51
11

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

documentation can be found here

Jayampathy Wijesena
  • 1,670
  • 1
  • 18
  • 26
7
<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()
Mackelito
  • 4,213
  • 5
  • 39
  • 78
6

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();
}

} 
Hodglem
  • 614
  • 9
  • 17
  • This is just wrong.. the MatInput directive has no Input() for "focus".. [focus]="true" will not do anything.. focus is a method to use in the controller "this.myInput.focus()" – Mackelito Apr 25 '18 at 06:42
  • @Mackelito The [focus] listed in the element is a directive I wrote. I wasn’t intimating that it was a directive that material input came with out of the box. – Hodglem Apr 25 '18 at 11:09
  • @Mackelito After I responded, you have left the downvote in place. I am not clear why. Can you either offer a way to improve the answer if it is unclear or remove the down vote please? – Hodglem Apr 27 '18 at 15:06
  • @Holdglem ops!.. just have been at home with my sick son... will upvote.. altho you might want to remove the "misleading" directives.. they don't really bring anything to the table ;) – Mackelito Apr 29 '18 at 19:44
  • (Btw: you need to update your answer if I'll be able to upvote ;) – Mackelito Apr 29 '18 at 19:45
  • @Mackelito I have updated the answer with the directive code for clarity. Thanks for being cool about it. Hope your son gets better soon. – Hodglem Apr 30 '18 at 15:23
0

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

FirstVertex
  • 3,657
  • 34
  • 33
-1

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.

Indiana
  • 313
  • 4
  • 8
-1

In input tag type cdkFocusInitial

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

If u want more info click here

Sushil
  • 670
  • 7
  • 14