【问题标题】:How to set autofocus on a matInput element on click event in Angular 6?如何在 Angular 6 中的单击事件上设置 matInput 元素的自动对焦?
【发布时间】:2019-01-01 19:16:21
【问题描述】:

类似于 Google 登录页面,我希望在点击事件后自动聚焦于输入元素。我已经尝试过@ViewChild('id') 和 document.getElementId('id')。两者都不起作用。它始终为 null 或未定义。我怎样才能做到这一点?

       <mat-form-field class="example-full-width col-sm-4">
        <input autofocus id="login-username" matInput 
       formControlName="userName" minlength="5" maxlength="20" 
       name="userName" placeholder="Username" required #input> 
      </mat-form-field>

        <div class="col-sm-12">
           <button (click)="changeView()" type="button" mat-raised-
             button color="primary">Next</button>
          </div>

         <mat-form-field class="example-full-width col-sm-4" 
          #passwordInput>
        <input autofocus type="password" matInput 
       placeholder="Password" minlength="5" maxlength="20" 
       formControlName="userPassword" #passwordInput>  
      </mat-form-field>

【问题讨论】:

  • 请显示您在 HTML 中引用 @ViewChild 的一些代码
  • 我在构造函数之前声明 @ViewChild('passwordInput') 并在调用时在 changeView() 中使用它。像这样。 changeView(){ this.passwordInputRef.nativeElement.focus();但这会引发错误。说 nativeElement 是未定义的。
  • 在 AfterViewInit 生命周期挂钩之前不会设置 ViewChild 属性
  • 设置focus()前需要添加timeout,否则会抛出nativeElementundefined错误

标签: angular html angular-material


【解决方案1】:

我混合了所有其他答案。这是它对我有用的唯一方法。

添加到任何 Typescript 功能

  @ViewChild('foobarElement') foobarElement: ElementRef;
      
  anyFunction() {
      setTimeout(() => this.foobarElement.nativeElement.focus());
  }

而在 HTML

  <input type="text"
    matInput 
    #foobarElement>

【讨论】:

    【解决方案2】:

    不幸的是,并非每个解决方案都能在渲染时始终使用自动对焦 matInput。这是我尝试过的:

    • HTML autofocus 属性
    • JSinput.focus()
    • cdkFocusInitial 来自@angular/cdk

    上述所有方法都可能有效,但在某些情况下它们似乎被破坏了。

    始终始终起作用的是使用matInput的高级api。这是一个使用这种方法的简单指令:

    import { Directive, OnInit } from '@angular/core';
    import { MatInput } from '@angular/material/input';
    
    @Directive({
      selector: '[matInputAutofocus]',
    })
    export class AutofocusDirective implements OnInit {
    
      constructor(private matInput: MatInput) { }
    
      ngOnInit() {
        setTimeout(() => this.matInput.focus());
      }
    
    }
    

    延迟聚焦元素需要超时,因为 matInput 在创建时还不能正常工作。用法:

    <mat-form-field>
      <input type="text" matInput matInputAutofocus>
    </mat-form-field>
    

    当然,将选择器命名为matInputAutofocus 是危险的,因为材料本身总有一天会出现这种解决方案。使用它需要您自担风险,或者只是用您的前缀重命名(推荐)。

    对焦同时选择输入值

    锦上添花的是增加了预先选择输入内容的可能性(这在大多数情况下更加用户友好),这会稍微改变实现:

    import { Directive, OnInit } from '@angular/core';
    import { MatInput } from '@angular/material/input';
        
    @Directive({
      selector: '[matInputAutofocus]',
    })
    export class AutofocusDirective implements OnInit {
    
      @Input()
      autofocusSelectValue = false;
    
      constructor(
        private matInput: MatInput,
        private elRef: ElementRef<HTMLInputElement>,
      ) { }
    
      ngOnInit(): void {
        setTimeout(() => {
          this.matInput.focus();
    
          if (this.autofocusSelectValue) {
            this.elRef.nativeElement.setSelectionRange(0, input.value.length);
          }
        });
      }
    
    }
    

    将其用作:

    <mat-form-field>
      <input type="text" matInput matInputAutofocus [autofocusSelectValue]="true">
    </mat-form-field>
    

    【讨论】:

    • 与在ngAfterViewInit() 中使用&lt;elementRef variable&gt;.nativeElement.focus() 访问ElementRef 相比,此解决方案的另一个优点是您无需为模板中使用matInput 的每个组件编写ngAfterViewInit()。
    • MatInput 导入应该是: import { MatInput } from '@angular/material/input';
    • @smnbbrv 当我在 *ngFor-Loop 创建的 mat-form-fields 数组上使用它时,焦点始终设置在数组的最后一个元素上。你知道如何解决这个问题吗?
    • @Phreneticus 我想最简单的方法是添加@Input('matInputAutofocus') enabled: boolean;,仅在它为真时运行 ngOnInit 部分,如果它是第一个(或另一个所需位置),则在 ngFor 中将属性设置为 true ,比如&lt;div *ngFor="let a of array; let first = first"&gt;...[matInputAutofocus]="first"
    【解决方案3】:

    您可以使用 Material 中的cdkFocusInitial

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

    请参阅orginal 答案。

    【讨论】:

      【解决方案4】:

      当你使用 Angular Material 时,你可以使用cdkFocusInitial 告诉库在组件准备好后你想要关注的地方。不需要原生方法:

      <mat-form-field class="example-full-width">
        <mat-label>My Label</mat-label>
        <textarea 
          cdkFocusInitial           <---------
          cdkTextareaAutosize
          matInput>
        </textarea>
      </mat-form-field>
      

      【讨论】:

      • 这对我很有用。谢谢!
      【解决方案5】:

      您需要使用模板引用来输入元素,然后使用 ViewChild 它将起作用

      示例:https://stackblitz.com/edit/angular-frqm8b

       <mat-form-field class="example-full-width col-sm-4">
              <input autofocus id="login-username" matInput 
             formControlName="userName" minlength="5" maxlength="20" 
             name="userName" placeholder="Username" required #input> 
            </mat-form-field>
      
              <div class="col-sm-12">
                 <button (click)="changeView()" type="button" mat-raised-
                   button color="primary">Next</button>
                </div>
      
               <mat-form-field class="example-full-width col-sm-4" 
                >
              <input autofocus type="password" matInput 
              ****#passwordInput****
             placeholder="Password" minlength="5" maxlength="20" 
             formControlName="userPassword" #passwordInput>  
            </mat-form-field>
      

      【讨论】:

        【解决方案6】:

        如果您想在页面加载后立即将焦点设置到输入字段,您只需将 HTML 属性应用于该元素即可,例如:

        &lt;input type="text" #input1 autofocus&gt;

        如果您想有条件地从您的 component.ts 执行此操作,请使用:

            import { Component, ElementRef, ViewChild, AfterViewInit} from 
            '@angular/core';
            ... 
        
         @ViewChild('input1') inputEl:ElementRef;
        
         ngAfterViewInit() {
         this.inputEl.nativeElement.focus();
         }
        

        或者你可以使用:

        首先从@angular/core 导入renderer2,然后,

            const element = this.renderer.selectRootElement('#input1');
        
         setTimeout(() => element.focus(), 0);
        

        无论您似乎对现有代码感到满意。

        【讨论】:

        • 简单和功能!
        猜你喜欢
        • 2020-03-17
        • 1970-01-01
        • 2023-03-30
        • 2016-02-23
        • 1970-01-01
        • 2018-02-06
        • 2021-01-19
        • 2020-06-07
        • 1970-01-01
        相关资源
        最近更新 更多