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

如何在文本输入框中添加固定连字符?Angular场景求助

实现带固定连字符的数字输入框

需求说明

需要实现一个数字输入框,满足以下要求:

  • 输入框默认显示格式为 ___-__-__-__-__,连字符固定显示
  • 数字通过按钮输入,输入规则为:前3位数字后自动添加连字符,后续每输入2位数字添加一个连字符
  • 连字符无需手动输入,始终作为固定视觉元素存在

方案一:视觉模拟固定连字符(推荐)

这种方式将连字符作为独立的视觉元素,实际输入框仅存储纯数字,避免连字符干扰业务逻辑。

1. 修改HTML结构

<div class="row">
  <p id="p" style="font-size: 30px;">Introduzca ubicación:
    <!-- 自定义输入容器,包含输入框和连字符 -->
    <div class="custom-input-container" style="margin-left: 10px; font-size: 30px; position: relative;">
      <input 
        style="width: 220px; font-size: 30px; letter-spacing: 22px; padding-left: 5px; border: none; outline: none;"
        type="text" 
        [value]="formattedDisplay" 
        id="code" 
        readonly
      >
      <!-- 固定连字符 -->
      <span class="hyphen" style="position: absolute; left: 85px; top: 0;">-</span>
      <span class="hyphen" style="position: absolute; left: 130px; top: 0;">-</span>
      <span class="hyphen" style="position: absolute; left: 175px; top: 0;">-</span>
      <span class="hyphen" style="position: absolute; left: 220px; top: 0;">-</span>
    </div>
    <button type="button" style="margin-left: 10px; font-size: 30px; border: white 3px solid;"
      class="btn btn-dark btn-lg" (click)="clear()">Borrar</button>
    <button type="button" style="margin-left: 10px; font-size: 30px; border: white 3px solid;"
      class="btn btn-dark btn-lg" (click)="allClear()">Borrar todo</button>
  </p>
</div>

<div class="calculator-keys">
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('0')" value="0">0</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('1')" value="1">1</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('2')" value="2">2</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('3')" value="3">3</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('4')" value="4">4</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('5')" value="5">5</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('6')" value="6">6</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('7')" value="7">7</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('8')" value="8">8</button>
  <button type="button" class="btn btn-light waves-effect" (click)="pressNum('9')" value="9">9</button>
</div>

2. 组件逻辑(Angular)

在组件类中维护纯数字的codeNum,同时生成用于显示的格式化字符串:

codeNum: string = '';
formattedDisplay: string = '';

pressNum(num: string) {
  // 限制总长度为9位数字(3+2*4)
  if (this.codeNum.length >= 9) return;
  this.codeNum += num;
  this.updateFormattedDisplay();
}

clear() {
  if (this.codeNum.length > 0) {
    this.codeNum = this.codeNum.slice(0, -1);
    this.updateFormattedDisplay();
  }
}

allClear() {
  this.codeNum = '';
  this.updateFormattedDisplay();
}

private updateFormattedDisplay() {
  // 根据数字生成带下划线的显示字符串
  let display = '';
  // 前3位
  display += this.codeNum.slice(0,3).padEnd(3, '_');
  // 后续每2位
  if (this.codeNum.length > 3) {
    const remaining = this.codeNum.slice(3);
    const chunks = remaining.match(/.{1,2}/g) || [];
    chunks.forEach((chunk, index) => {
      display += '-' + chunk.padEnd(2, '_');
    });
    // 补全剩余的连字符和下划线
    const neededChunks = 4 - chunks.length;
    for (let i=0; i<neededChunks; i++) {
      display += '-__';
    }
  } else {
    // 补全剩下的连字符和下划线
    display += '-__-__-__-__';
  }
  this.formattedDisplay = display;
}

方案二:动态格式化输入值

直接在codeNum中插入连字符,适用于需要连字符包含在输入值中的场景:

组件逻辑修改

codeNum: string = '';

pressNum(num: string) {
  // 先去掉现有连字符,得到纯数字
  const pureNum = this.codeNum.replace(/-/g, '');
  if (pureNum.length >= 9) return;
  const newPureNum = pureNum + num;
  // 格式化带连字符的字符串
  let formatted = '';
  formatted += newPureNum.slice(0,3);
  if (newPureNum.length > 3) {
    const remaining = newPureNum.slice(3);
    const chunks = remaining.match(/.{1,2}/g) || [];
    chunks.forEach(chunk => {
      formatted += '-' + chunk;
    });
  }
  // 补全默认的下划线和连字符
  const totalLength = formatted.length;
  if (totalLength < 3) {
    formatted = formatted.padEnd(3, '_') + '-__-__-__-__';
  } else if (totalLength >=3 && totalLength < 5) {
    formatted = formatted + '-' + '__'.slice(formatted.length-3) + '-__-__-__';
  } else if (totalLength >=5 && totalLength <8) {
    formatted = formatted + '-' + '__'.slice(formatted.length-5) + '-__-__';
  } else if (totalLength >=8 && totalLength <11) {
    formatted = formatted + '-' + '__'.slice(formatted.length-8) + '-__';
  } else if (totalLength >=11 && totalLength <14) {
    formatted = formatted + '-' + '__'.slice(formatted.length-11);
  }
  this.codeNum = formatted;
}

clear() {
  if (this.codeNum.length === 0) return;
  // 如果最后一位是连字符,直接删除
  if (this.codeNum.endsWith('-')) {
    this.codeNum = this.codeNum.slice(0, -1);
  } else {
    // 否则删除最后一个数字,再处理连字符
    const pureNum = this.codeNum.replace(/-/g, '').slice(0, -1);
    // 重新格式化
    let formatted = '';
    formatted += pureNum.slice(0,3);
    if (pureNum.length >3) {
      const remaining = pureNum.slice(3);
      const chunks = remaining.match(/.{1,2}/g) || [];
      chunks.forEach(chunk => {
        formatted += '-' + chunk;
      });
    }
    // 补全下划线
    const totalLength = formatted.length;
    if (totalLength <3) {
      formatted = formatted.padEnd(3, '_') + '-__-__-__-__';
    } else if (totalLength >=3 && totalLength <5) {
      formatted = formatted + '-' + '__'.slice(formatted.length-3) + '-__-__-__';
    } else if (totalLength >=5 && totalLength <8) {
      formatted = formatted + '-' + '__'.slice(formatted.length-5) + '-__-__';
    } else if (totalLength >=8 && totalLength <11) {
      formatted = formatted + '-' + '__'.slice(formatted.length-8) + '-__';
    } else if (totalLength >=11 && totalLength <14) {
      formatted = formatted + '-' + '__'.slice(formatted.length-11);
    }
    this.codeNum = formatted;
  }
}

allClear() {
  this.codeNum = '___-__-__-__-__';
}

说明

  • 方案一分离了显示和实际值,连字符仅作为视觉元素,业务逻辑只处理纯数字,更简洁可靠
  • 方案二将连字符包含在输入值中,适合需要提交带连字符格式数据的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:10:21