【问题标题】:How to manually set focus on mat-form-field in Angular 6如何在 Angular 6 中手动设置 mat-form-field 焦点
【发布时间】:2019-02-08 02:46:13
【问题描述】:

我是 angular 新手,在我的应用程序中,我有一个 mat-dialog,其中有两种形式,即 Login 和 SignUp。

一旦我第一次打开对话框,自动焦点设置在用户名字段上。问题是当我导航到按钮上的注册表单时单击该表单的名字字段没有自动获得焦点,同样的方式从注册导航到登录用户名字段现在不会自动聚焦。

我尝试了一些 stackoverflow 解决方案,但没有解决我的问题。

popupScreen.component.html

<form class="login" *ngIf="isLoginHide">
    <mat-form-field>
        <input matInput placeholder="username">
    </mat-form-field>
    <mat-form-field>
        <input matInput placeholder="password">
    </mat-form-field>

    <button mat-button color="primary">Login</button>
    <button mat-button (click)="hideLogin($event)" color="accent">SignUp</button>
</form>

<form class="SignUp" *ngIf="isSignUpHide">
    <mat-form-field>
        <input matInput placeholder="First Name">
    </mat-form-field>
    <mat-form-field>
        <input matInput placeholder="Last Name">
    </mat-form-field>
    <mat-form-field>
        <input matInput placeholder="username">
    </mat-form-field>
    <mat-form-field>
        <input matInput placeholder="password">
    </mat-form-field>

    <button mat-button (click)="hideSignUp($event)" color="primary">Login</button>
    <button mat-button color="accent">SignUp</button>
</form>

谁能帮我解决这个问题。

【问题讨论】:

    标签: angular typescript angular-material


    【解决方案1】:

    请在您想要关注的输入字段中使用cdkFocusInitial 属性。

    <mat-form-field>
        <input matInput placeholder="username" #usernameInput cdkFocusInitial>
    </mat-form-field>
    

    【讨论】:

    • 这不起作用。如果是这样,请提供一个 stackblitz 示例
    • @kumardippu Trust me it works - 如果没有看到工作示例,我不会相信自己 ;-)
    • 将 cdkFocusInitial 放在 mat-slide-toggle 上为我工作
    • 为我工作,当我打开 MatDialog 时,焦点在 MatExpansionPanel 但我希望它在按钮上。在按钮上设置cdkFocusInitial 就是这样做的。
    • 这不是信任问题。这是故障排除的问题。一个工作示例可以揭示操作缺少的内容。可能是包版本、语法差异或其他干扰等简单的东西。
    【解决方案2】:

    几乎 .. :-),如果您使用 MatSelect 之类的材料组件 - 上述解决方案不起作用。您可以在下面找到适合我的解决方案。

    <mat-form-field>
        <mat-select #myElement ......>
           ..........
        </mat-select>
    <mat-form-field>
    

    然后在组件中...

    @ViewChild('myElement') firstItem: MatSelect;
    
    ngAfterViewInit() {
       this.firstItem.focus();
       this.cd.detectChanges();
    }
    

    请记住,您必须在设置焦点后强制更改检测以避免 Angular 错误:“ExpressionChangedAfterItHasBeenCheckedError”(顺便说一句,您还必须在您的组件构造器)

    希望对您有所帮助...

    【讨论】:

    • 您的示例中的变量cd 来自哪里?
    • cd 是前面提到的“ChangeDetectorRef”。
    • 它将作为注入依赖项进入构造函数。
    【解决方案3】:

    您可以使用 MatInput 设置自动对焦

    这是一个例子,

    component.html

    <mat-form-field>
        <input matInput placeholder="First Name" #firstname="matInput">
    </mat-form-field>
    

    component.ts

    import { MatInput } from '@angular/material/input';
    
    export class Component implements OnInit {
    
        @ViewChild('firstname') nameInput: MatInput;
    
        ngOnInit() {
           this.nameInput.focus();
        }
    }
    

    【讨论】:

    • this.nameInput 是undefined,当你在ngOnInit 中使用它时,你需要在ngAfterViewInit 中调用它,但是你会得到@jspassov 提到的错误
    • 我不相信已经过去快两年了,还没有找到解决问题的办法
    【解决方案4】:

    这在 Angular 8 中适用于我:

    <mat-form-field>
        <input matInput placeholder="First Name" #firstname>
    </mat-form-field>
    

    .ts

    export class TestComponent implements OnInit {
    
        @ViewChild('firstname', {static: true}) firstname:any;
    
        ngOnInit() {
          this.firstname.nativeElement.focus();
        }
    
    }
    

    【讨论】:

    • 这对我来说是正确的答案(Angular 9,Material 9)。对于打字顽固分子,请使用ElementRef 而不是any; (并且不需要static: true
    【解决方案5】:

    您是否尝试将autofocus 添加到名字的表单字段?

    <form class="SignUp" *ngIf="isSignUpHide">
        <mat-form-field>
            <input matInput placeholder="First Name" autofocus>
        </mat-form-field>
        <mat-form-field>
            <input matInput placeholder="Last Name">
        </mat-form-field>
        <mat-form-field>
            <input matInput placeholder="username">
        </mat-form-field>
        <mat-form-field>
            <input matInput placeholder="password">
        </mat-form-field>
    
        <button mat-button (click)="hideSignUp($event)" color="primary">Login</button>
        <button mat-button color="accent">SignUp</button>
    </form>
    

    【讨论】:

    • 是的,如果我使用按钮单击在两个表单之间导航而不与输入字段进行任何交互,则它第一次起作用,它从第二次不起作用@Prashant 起不起作用@Prashant
    • 这在使用 Angular 10 + 材料的表单中运行良好,谢谢!
    【解决方案6】:

    use 可以使用原生元素的焦点。

    没有测试过这段代码,但类似这样:

    <mat-form-field>
        <input matInput placeholder="username" #usernameInput>
    </mat-form-field>
    

    在您的组件上:

    @ViewChild('usernameInput') usrFld: ElementRef;
    
    ngAfterViewInit() {
      this.usrFld.nativeElement.focus();
    }
    

    p.s:您应该路由到注册组件,而不是使用ngIf 进行导航。

    【讨论】:

      【解决方案7】:

      这对我有用:

      <mat-label >Radio name:</mat-label>
         <input type="text" #inputName="matInput" matInput formControlName="name" placeholder="Type radio name"/>
      </mat-form-field>
      
        @ViewChild('inputName', { static: false }) inputName: MatInput;
      
        ngAfterViewInit(): void {
          setTimeout(() => this.inputName.focus(), 0);
        }
      

      setTimeout 是一种避免更改检测问题的技巧。我不知道为什么,但在我的情况下手动执行更改检测不起作用。

      【讨论】:

        【解决方案8】:

        对于 MatDialog,您必须使用 setTimeout

        延迟操作
        <mat-form-field>
          <mat-label>Name</mat-label>
          <input #inputName="matInput" matInput formControlName="name">
        </mat-form-field>
        
        @ViewChild('inputName') inputName: MatInput;
        
        ngAfterViewInit() {
          setTimeout(() => {
            this.inputName.focus();
          });
        }
        

        【讨论】:

          【解决方案9】:

          解决这个问题很简单,使用 Angular Material CDK 选项 cdkFocusInitial

          <mat-form-field>
              <input matInput placeholder="username" cdkFocusInitial>
          </mat-form-field>
          

          【讨论】:

            【解决方案10】:

            请注意,根据组件显示的时间和方式,ngOnInit 可能不是设置焦点的地方。

            例如,如果 ComponentOne 的 html 如下所示:

              <ng-container *ngIf='something === true'>
                <app-component-two></app-component-two>
              </ng-container>
            

            而 ComponentTwo 有您的输入元素,并且 ComponentTwo 的 ts 文件设置正确,然后将其放入您的 component-two.component.ts 文件中:

            ngOnInit() {
              this.myInput.focus();
            }
            

            可能无法正常工作,因为 ComponentTwo 的 html 尚未呈现,这意味着即使 ViewChild 正确,this.myInput 尚未呈现并且为空。

            ngAfterViewInit() {
              this.myInput.focus();
            }
            

            即使你没有嵌套组件,你可能仍然需要注意 html 的生命周期,以确保你的焦点命令在输入元素被渲染之后发生。

            查看https://angular.io/guide/lifecycle-hooks#lifecycle-event-sequence 了解有关角度生命周期的更多信息。

            【讨论】:

              【解决方案11】:

              这么简单和普通的事情,但上面的大部分都不适合我。

              cdkFocusInitial 效果很好,除非您使用步进器控件或等效控件,您希望将新输入集中在 stepper.next() 上。

              我最终没有使用 viewchild 来获取对对象的引用,而是使用老式的 id。

              public setFocus(input: string) {
                 const targetElem = document.getElementById(input);
                 setTimeout(function waitTargetElem() {
                  if (document.body.contains(targetElem)) {
                    targetElem.focus();
                  } else {
                    setTimeout(waitTargetElem, 100);
                  }
                }, 500);
              }
              

              用...调用它

              this.setfocus('id of your input')
              

              【讨论】:

                猜你喜欢
                • 2021-03-12
                • 2018-09-27
                • 1970-01-01
                • 2019-07-12
                • 2019-02-18
                • 2018-07-10
                • 2020-10-26
                • 2018-04-16
                • 2019-01-01
                相关资源
                最近更新 更多