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

Angular 4 Input Directive:如何在表单提交时触发指令事件移除格式?

当然可以实现!而且有几种不同的方式来处理这个需求,我来给你详细拆解一下:

核心思路

你的本质需求是:视图层显示哥伦比亚格式的字符串,模型层保存原始数值,提交时确保模型里是未格式化的原始值。我们可以从「指令内部集成双向转换」和「提交时手动触发转换」两个方向来实现。


方法一:利用 ngModel 自动处理(推荐)

这是最符合Angular双向绑定设计的方案——让指令自动在视图和模型之间做转换,提交时模型已经是原始数值,无需额外操作。

指令实现示例

angular.module('yourApp').directive('colombianNumber', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      // 1. 模型 → 视图:把原始数值转成哥伦比亚格式
      ngModel.$formatters.push(function(rawValue) {
        if (!angular.isNumber(rawValue)) return '';
        // 拆分整数和小数部分,添加千分位点,替换小数分隔符为逗号
        const [integerPart, decimalPart] = rawValue.toString().split('.');
        const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
        const formattedDecimal = decimalPart ? `,${decimalPart.slice(0, 2)}` : '';
        return formattedInteger + formattedDecimal;
      });

      // 2. 视图 → 模型:把格式化字符串转成原始数值
      ngModel.$parsers.push(function(formattedValue) {
        if (!formattedValue) return null;
        // 移除千分位点,把逗号换回点,转成浮点数
        return parseFloat(formattedValue.replace(/\./g, '').replace(',', '.')) || null;
      });

      // 3. 实时输入时维护光标位置(优化用户体验)
      element.on('input', function() {
        const cursorPos = element[0].selectionStart;
        const originalLength = element.val().length;
        // 触发ngModel的转换逻辑,更新视图
        ngModel.$setViewValue(element.val());
        scope.$apply();
        // 调整光标位置,避免输入时光标跳到末尾
        const newLength = element.val().length;
        element[0].selectionStart = element[0].selectionEnd = cursorPos + (newLength - originalLength);
      });
    }
  };
});

使用方式

<form ng-submit="handleSubmit()">
  <input type="text" colombian-number ng-model="transaction.amount">
  <button type="submit">提交</button>
</form>

提交逻辑

$scope.handleSubmit = function() {
  // 直接用模型值即可,它已经是原始数值(比如1000.25)
  console.log($scope.transaction.amount);
  // 这里写你的提交逻辑
};

方法二:提交时手动触发指令内的转换

如果你不想改动现有指令的实时格式化逻辑,也可以在指令中暴露一个「反格式化」方法,在提交时手动调用它来更新模型。

修改现有指令

angular.module('yourApp').directive('colombianNumber', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      // 你的现有格式化逻辑(onKeyPress处理)
      element.on('keypress', function(e) {
        // 这里保留你原来的实时格式化代码
        const currentValue = element.val();
        // 你的格式化处理...
        element.val(yourFormatFunction(currentValue));
      });

      // 定义反格式化函数
      function unformatValue(formattedStr) {
        if (!formattedStr) return null;
        return parseFloat(formattedStr.replace(/\./g, '').replace(',', '.')) || null;
      }

      // 把方法暴露给DOM元素,方便外部调用
      element[0].syncRawValue = function() {
        const formatted = element.val();
        const rawValue = unformatValue(formatted);
        ngModel.$setViewValue(rawValue);
        scope.$apply(); // 通知Angular更新模型
      };
    }
  };
});

提交时调用

<input type="text" colombian-number ng-model="transaction.amount" id="amountInput">
<button ng-click="handleSubmit()">提交</button>
$scope.handleSubmit = function() {
  // 获取输入元素,调用指令暴露的方法
  const inputEl = document.getElementById('amountInput');
  inputEl.syncRawValue();
  
  // 现在模型里就是原始数值了
  console.log($scope.transaction.amount);
  // 执行提交逻辑
};

额外优化建议

  • 如果是表单提交,也可以在指令里监听表单的submit事件,自动触发转换,无需在控制器里写额外代码:
    // 在指令link函数末尾添加
    const form = element.closest('form');
    if (form) {
      form.addEventListener('submit', function() {
        element[0].syncRawValue();
        scope.$apply();
      });
    }
    
  • 实时格式化时一定要处理光标位置,不然用户输入体验会很差,方法一里已经包含了这个逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:25:00