Angular 2 Material输入框无法获取焦点

14

输入位于模态对话框内。我不知道为什么它不起作用。我查看了官方文档,它列出了可以传递给元素的焦点,但它没有起作用?

有谁知道原因吗?

Angular材料-输入文档

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

你能更好地描述一下问题吗?你无法编译代码吗?运行时崩溃了吗?它的行为与预期不同吗?错误信息是什么?期望的行为是什么?实际的行为是什么? - Codo
看起来你必须使用 focused="true" - Edric
7个回答

14
你的尝试没有成功,因为:
- focused是一个驱动mdInputContainermat-focused类的属性。你可以使用它来判断输入框是否获得了焦点,但无法使用它来改变焦点状态。 - focusmdInput上的一个方法,可让你以编程方式将焦点放在输入框上。你可以使用类似于ViewChild('myInput')的内容作为myInput,并调用myInput.focus()。 但最简单的实现方式是使用标准的autofocus属性:
<md-input-container>
    <input mdInput type="text" name="a" placeholder="zzzz" autofocus>
</md-input-container>

13
请注意,“自动对焦”仅在页面首次加载时起作用。对于我们的应用程序,在用户添加新“项目”时,我们正在编译和注入一个窗口。“自动对焦”似乎只能在用户尝试添加项目时第一次起作用,之后就不起作用了。只是需要记住这一点。 - kbpontius
我注意到有时页面加载后其他元素会“窃取”焦点。例如,无论另一个元素是否设置了自动对焦,我的<mat-autocomplete>似乎都会获得焦点。 - Jus10

11

你尝试过使用 cdkFocusInitial 吗?它可以指定在初始化时将获得焦点的元素。

文档可以在这里找到。


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>

然后在控制器中:

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

this.emailInput.focus()的作用实际上是"elementRef.nativeElement.focus()",具体可以参考以下链接:

https://github.com/angular/material2/blob/master/src/lib/input/input.ts#L287

因此,您也可以自己这样做:

this.emailInput.nativeElement.focus()

6

我曾经也遇到过同样的问题。当我使用F6快捷键打开对话框时,输入框无法获得焦点。后来发现,我没有阻止F6默认的行为,而F6会高亮显示浏览器的URL地址栏,从而夺走了焦点。

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

此外,没有任何神奇的标签属性可用。自动聚焦、已聚焦、聚焦等都不行。我不得不创建一个指令并在我的输入元素中使用它。我通过这个答案获得了帮助。
在添加指令后,以下是该元素的内容(numberOnly是另一个用于只能输入数字的指令):
<md-input-container> <input mdInput [focus]="true" [numberOnly]="true"/></md-input-container>

**编辑:根据@ Mackelito的建议,添加指令代码以提高清晰度。 以下是我编写的指令,使用了我上面链接的答案。请注意,material已将其标签标签更改为<input matInput>而不是<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();
}

} 

这是错误的。MatInput指令没有“focus”的Input()方法。[focus]="true"不会起作用。focus是在控制器中使用的方法,“this.myInput.focus()”。 - Mackelito
@Mackelito,元素中列出的[focus]是我编写的指令。我并没有暗示这是一个材料输入框架自带的指令。 - Hodglem
@Mackelito 在我回复后,您仍然保留了负评。我不清楚原因。如果我的回答不够清晰,请提供改进的方法,或者请撤销负评。 - Hodglem
@Holdglem 哎呀!我刚刚在家照顾生病的儿子... 我会点赞的...虽然你可能想要删除那些“误导性”的指令...它们并没有真正为表格带来任何东西 ;) - Mackelito
(顺便说一句:如果我能够点赞,您需要更新您的答案 ;)) - Mackelito
@Mackelito,我已经更新了指令代码以增加清晰度。感谢你的配合。希望你的儿子早日康复。 - Hodglem

0

通常情况下,您可以使用模板标记设置焦点,而无需任何TypeScript代码。但是对于Dialog,您需要使用@Mackelito的解决方案,使用@ViewChildngAfterViewInit()

我必须在Menu中获取焦点在TextArea上,当该Menu出现时。幸运的是,Menu有一个(menuOpened)事件可以绑定。

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

重要的部分在于 (menuOpened)="newTypes.focus()",我们可以看到 newTypes 是一个附加到我想要聚焦的 TextArea 的 TemplateRef 变量,标记为 <textarea #newTypes

这里有一张屏幕截图,显示了我的菜单打开并立即将焦点放在其中的 TextArea 上。

enter image description here


-1

尝试在设置输入获取焦点之前添加一些延迟。我已经将此行为制作成指令供您参考。

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) { }
}

例子

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

你可以在这里尝试它。

-1
在输入标签中输入 cdkFocusInitial
<input matInput [(ngModule)]="cityName" cdkFocusInitial>

如果您想获取更多信息请点击这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接