如何在<md-input-container>中实现金额千分位分隔及保留两位小数
Hey there, let's solve this formatting issue for your unit price input. The key challenge here is balancing a user-friendly formatted display (thousand separators + two fixed decimals) while keeping the underlying ng-model value as a valid number for your business logic. Here's a step-by-step implementation:
1. Create a Custom AngularJS Directive
We'll build a directive that handles the formatting when the input loses focus, and reverts to a raw number when focused for editing. This keeps the model clean while making the display user-friendly.
Add this directive to your AngularJS module:
angular.module('yourAppModule') .directive('formatCurrency', function($filter) { return { require: 'ngModel', link: function(scope, element, attrs, ngModelCtrl) { // Format value for display when input loses focus element.on('blur', function() { var value = ngModelCtrl.$modelValue; if (!value) return; // Format to 2 decimal places with thousand separators var formattedValue = $filter('number')(value, 2); ngModelCtrl.$setViewValue(formattedValue); ngModelCtrl.$render(); }); // Revert to raw number when focusing for editing element.on('focus', function() { var value = ngModelCtrl.$modelValue; if (!value) return; ngModelCtrl.$setViewValue(value.toString()); ngModelCtrl.$render(); // Move cursor to end of input for better UX setTimeout(function() { element[0].setSelectionRange(element[0].value.length, element[0].value.length); }, 0); }); // Parse formatted string back to a number for the model ngModelCtrl.$parsers.push(function(viewValue) { if (!viewValue) return null; // Remove non-numeric characters except decimal point var rawValue = viewValue.replace(/[^0-9.]/g, ''); // Ensure exactly two decimal places var parts = rawValue.split('.'); if (parts.length === 1) { rawValue += '.00'; } else if (parts[1].length > 2) { parts[1] = parts[1].substring(0, 2); rawValue = parts.join('.'); } return parseFloat(rawValue) || null; }); // Format initial value when directive loads scope.$watch(function() { return ngModelCtrl.$modelValue; }, function(newVal) { if (newVal !== undefined && !element.is(':focus')) { var formattedValue = $filter('number')(newVal, 2); ngModelCtrl.$setViewValue(formattedValue); ngModelCtrl.$render(); } }); } }; });
2. Update Your HTML Markup
Modify your existing <input> element to use the new directive, and switch the type to text (since type="number" doesn't support thousand separators natively). We'll keep your existing validation and model binding intact:
<td md-cell class="min-width-120px-imp text-right padding-right-10"> <md-input-container flex class="margin-0" ng-show="!vm.grn.itemdetails[$index].isfree"> <label translate class="padding-left-0">COMMON.UNITPRICE</label> <input id="grnUnitPrice{{$index}}" name="grnUnitPrice{{$index}}" class="text-right" type="text" <!-- Changed from number to text for separator support --> enterastab ng-required="!vm.grn.itemdetails[$index].isfree" ng-model="vm.grn.itemdetails[$index].unitprice" ng-pattern="vm.amountPattern" format-currency <!-- Added our custom formatting directive --> ng-change="vm.updatePriceCalculations($index)" <!-- Completed your ng-change logic --> > </md-input-container> </td>
3. Adjust Your Amount Pattern (Optional)
If your existing vm.amountPattern is tailored for type="number", update it to allow thousand separators in the input:
// Pattern allowing numbers with thousand separators and exactly two decimals vm.amountPattern = /^\d{1,3}(,\d{3})*(\.\d{2})?$/;
Key Notes
- Model Integrity: The
ng-modelvalue remains a numeric type (not a string), so your business logic can use it directly for calculations. - User Experience: When the user clicks into the input, it reverts to a raw number (no separators) for easy editing, and re-formats when they click away.
- Decimal Enforcement: The directive ensures exactly two decimal places are always displayed, even if the input doesn't include them.
内容的提问来源于stack exchange,提问作者Raghul

