You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular PWA iOS端Number类型输入框初始化后自动失焦问题求助

iOS端Number类型输入框初始化聚焦后立刻失焦问题

我开发了基于Angular 15.1.0的PWA应用,使用Angular Material组件。点击按钮弹出对话框,输入框为text类型时,在ngOnInit中调用focus()可正常聚焦;改为number类型后,iOS端输入框初始化聚焦后立刻失焦(键盘仅显示约0.2秒),Android端无此问题。


相关代码

HTML代码

<div class="container">
  <h2 class="title" mat-dialog-title>Insert value</h2>
  <div class="flex column" style="height: 100%; width: 100%;">
    <form>
      <input autocomplete="disable" class="input" id="value" type="number" inputmode="decimal" style="width: 60vw;" [(ngModel)]="input"
        name="value">
    </form>
    <mat-dialog-actions style="display: flex; flex-direction: row; justify-content: space-around; width: 40vw;">
      <button class="button" mat-dialog-close mat-dialog-close="false">Cancel</button>
      <button class="button" mat-dialog-close [mat-dialog-close]="input">Insert</button>
    </mat-dialog-actions>
  </div>
</div>

TS组件代码

import { Component } from '@angular/core';

@Component({
  selector: 'app-number-dialog',
  templateUrl: './number-dialog.component.html',
  styleUrls: ['./number-dialog.component.css']
})
export class NumberDialogComponent {

  input!: any

  ngOnInit(): void {
    document.getElementById("value")?.focus()
  }

}

对话框打开函数

addWalletMovement(entry: boolean) {
    const db = getDatabase()
    const user = auth.currentUser

    if (user !== null) {
      const uid = user.uid;
      // 打开对话框
      let dialogRef = this.dialog.open(NumberDialogComponent, {
        width: '80vw',
        panelClass: 'containerDialog',
        position: {
          top: '20vh'
        }

      })
      dialogRef.afterClosed().subscribe(result => {
        if (result !== "false") {
          const folderListRef = ref(db, 'walletfolders/' + uid + "/" + this.walletView.key)
          set(folderListRef, {
            key: this.walletView.key,
            name: this.walletView.name,
            movement: this.walletView.movement ?
              [{ value: result as number, entry: entry }, ...this.walletView.movement] :
              [{ value: result as number, entry: entry }],
          }).catch((error) => {
            console.error(error);
          })
        }
      })
    }
  }

原因分析

iOS Safari(包括PWA运行环境)对number类型输入框的焦点处理有特殊逻辑:

  • Angular Material对话框的渲染动画、布局调整,或Angular的变更检测流程,会在ngOnInit执行后触发额外UI操作,覆盖输入框的焦点状态
  • number类型输入框在iOS上的原生焦点触发逻辑与text类型不同,直接调用focus()的时机过早,会被后续系统事件打断

解决方案

方案1:延迟调用focus()

通过setTimeout延迟聚焦操作,确保对话框完全渲染完成后再执行:

ngOnInit(): void {
  setTimeout(() => {
    document.getElementById("value")?.focus();
  }, 100); // 可根据实际测试调整延迟时长
}

方案2:使用ViewChild+AfterViewInit钩子

改用Angular视图查询获取输入框,在视图完全初始化后执行聚焦,避免直接操作DOM:

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-number-dialog',
  templateUrl: './number-dialog.component.html',
  styleUrls: ['./number-dialog.component.css']
})
export class NumberDialogComponent implements AfterViewInit {

  input!: any;
  @ViewChild('valueInput') valueInput!: ElementRef<HTMLInputElement>;

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.valueInput.nativeElement.focus();
    }, 50);
  }
}

对应的HTML需添加模板引用:

<input #valueInput autocomplete="disable" class="input" id="value" type="number" inputmode="decimal" style="width: 60vw;" [(ngModel)]="input" name="value">

方案3:临时关闭对话框动画

若怀疑是动画导致焦点丢失,可尝试关闭对话框动画验证:

let dialogRef = this.dialog.open(NumberDialogComponent, {
  width: '80vw',
  panelClass: 'containerDialog',
  position: {
    top: '20vh'
  },
  animationEnabled: false // 关闭动画
})

内容的提问来源于stack exchange,提问作者Giusto Piedimonte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 04:05:19