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

Angular实现手机号输入框格式化(614-123-1234格式)求助

Angular手机号格式化输入框实现方案

要实现XXX-XXX-XXXX格式的手机号输入框,不用jQuery的话,推荐两种纯Angular方案,适配表单控件场景:

方案一:组件内监听表单控件变化

适合单个组件内使用,逻辑直接嵌入组件:

1. 修改输入框模板

把type="number"改成type="text"(数字类型无法显示横杠),移除原生onKeyPress事件:

<input type='text' class="input" formControlName="cel" id="cel" name="cel">

2. 组件类中处理格式化逻辑

通过监听表单控件的valueChanges事件,实时处理输入内容:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'your-component-selector',
  templateUrl: './your-component.component.html'
})
export class YourComponent implements OnInit {
  form: FormGroup;
  private lastProcessedValue = '';

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      cel: ['']
    });
  }

  ngOnInit(): void {
    const phoneControl = this.form.get('cel');
    phoneControl?.valueChanges.subscribe(rawValue => {
      // 只保留输入中的数字
      const numericValue = rawValue.replace(/\D/g, '');
      // 避免重复处理导致循环
      if (numericValue === this.lastProcessedValue.replace(/\D/g, '')) return;

      // 拼接成XXX-XXX-XXXX格式
      let formatted = '';
      if (numericValue.length > 0) {
        formatted += numericValue.slice(0, 3);
        if (numericValue.length >= 4) {
          formatted += '-' + numericValue.slice(3, 6);
          if (numericValue.length >= 7) {
            formatted += '-' + numericValue.slice(6, 10);
          }
        }
      }

      this.lastProcessedValue = formatted;
      // 更新表单值,不触发valueChanges循环
      phoneControl.setValue(formatted, { emitEvent: false });
    });
  }
}

方案二:自定义指令(推荐,可复用)

封装成指令后,任何输入框都能直接复用格式化逻辑:

1. 创建手机号掩码指令

import { Directive, HostListener, ElementRef } from '@angular/core';

@Directive({
  selector: '[appPhoneMask]'
})
export class PhoneMaskDirective {
  constructor(private el: ElementRef) {}

  // 监听输入事件,处理格式化
  @HostListener('input', ['$event']) onInput(event: Event): void {
    const input = this.el.nativeElement;
    const numericValue = input.value.replace(/\D/g, '');
    let formatted = '';

    if (numericValue.length > 0) {
      formatted += numericValue.slice(0, 3);
      if (numericValue.length >= 4) {
        formatted += '-' + numericValue.slice(3, 6);
        if (numericValue.length >= 7) {
          formatted += '-' + numericValue.slice(6, 10);
        }
      }
    }

    // 保存光标位置,避免格式化后光标跳转到末尾
    const start = input.selectionStart;
    const end = input.selectionEnd;
    input.value = formatted;
    // 恢复光标位置
    if (start !== null && end !== null) {
      input.setSelectionRange(start, end);
    }
  }

  // 限制只能输入数字和必要的控制键
  @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void {
    const allowedKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'];
    const isNumeric = /[0-9]/.test(event.key);
    if (!isNumeric && !allowedKeys.includes(event.key)) {
      event.preventDefault();
    }
  }
}

2. 在模板中使用指令

同样把输入框改成type="text",添加指令属性:

<input type='text' class="input" formControlName="cel" id="cel" name="cel" appPhoneMask>

额外提示

  • 表单提交时,若需要纯数字的手机号,可通过this.form.get('cel')?.value.replace(/\D/g, '')提取数字部分。
  • 指令方案还能扩展支持删除、光标定位等细节,用户体验更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 07:10:23