Number Field with currency symbol, thousand separator & international support ExtJS4
/* * GNU General Public License Usage * This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. * * http://www.gnu.org/licenses/lgpl.html * * @description: This class provide aditional format to numbers by extending Ext.form.field.Number * * @author: Greivin Britton * @email: brittongr@gmail.com * @version: 2 compatible with ExtJS 4 */ Ext.define('Ext.ux.form.NumericField', { extend: 'Ext.form.field.Number',//Extending the NumberField alias: 'widget.numericfield',//Defining the xtype, currencySymbol: null, currencySymbolPos : 'right', // left , right useThousandSeparator: true, thousandSeparator: ',', alwaysDisplayDecimals: false, fieldStyle: 'text-align: right;', hideTrigger:true, initComponent: function(){ if (this.useThousandSeparator && this.decimalSeparator == ',' && this.thousandSeparator == ',') this.thousandSeparator = '.'; else if (this.allowDecimals && this.thousandSeparator == '.' && this.decimalSeparator == '.') this.decimalSeparator = ','; this.callParent(arguments); }, setValue: function(value){ Ext.ux.form.NumericField.superclass.setValue.call(this, value != null ? value.toString().replace('.', this.decimalSeparator) : value); this.setRawValue(this.getFormattedValue(this.getValue())); }, getFormattedValue: function(value){ if (Ext.isEmpty(value) || !this.hasFormat()) return value; else { var neg = null; value = (neg = value < 0) ? value * -1 : value; value = this.allowDecimals && this.alwaysDisplayDecimals ? value.toFixed(this.decimalPrecision) : value; if (this.useThousandSeparator) { if (this.useThousandSeparator && Ext.isEmpty(this.thousandSeparator)) throw ('NumberFormatException: invalid thousandSeparator, property must has a valid character.'); if (this.thousandSeparator == this.decimalSeparator) throw ('NumberFormatException: invalid thousandSeparator, thousand separator must be different from decimalSeparator.'); value = value.toString(); var ps = value.split('.'); ps[1] = ps[1] ? ps[1] : null; var whole = ps[0]; var r = /(\d+)(\d{3})/; var ts = this.thousandSeparator; while (r.test(whole)) whole = whole.replace(r, '$1' + ts + '$2'); value = whole + (ps[1] ? this.decimalSeparator + ps[1] : ''); } if (this.currencySymbolPos == 'right') { return Ext.String.format('{0}{1}{2}', (neg ? '-' : ''), value, (Ext.isEmpty(this.currencySymbol) ? '' : ' ' + this.currencySymbol)); } else { return Ext.String.format('{0}{1}{2}', (neg ? '-' : ''), (Ext.isEmpty(this.currencySymbol) ? '' : this.currencySymbol + ' '), value); } } }, /** * overrides parseValue to remove the format applied by this class */ parseValue: function(value){ //Replace the currency symbol and thousand separator return Ext.ux.form.NumericField.superclass.parseValue.call(this, this.removeFormat(value)); }, /** * Remove only the format added by this class to let the superclass validate with it's rules. * @param {Object} value */ removeFormat: function(value){ if (Ext.isEmpty(value) || !this.hasFormat()) return value; else { if (this.currencySymbolPos == 'right') { value = value.toString().replace(' ' + this.currencySymbol, ''); } else { value = value.toString().replace(this.currencySymbol + ' ', ''); } value = this.useThousandSeparator ? value.replace(new RegExp('[' + this.thousandSeparator + ']', 'g'), '') : value; return value; } }, /** * Remove the format before validating the the value. * @param {Number} value */ getErrors: function(value){ return Ext.ux.form.NumericField.superclass.getErrors.call(this, this.removeFormat(value)); }, hasFormat: function(){ return this.decimalSeparator != '.' || (this.useThousandSeparator == true && this.getRawValue() != null) || !Ext.isEmpty(this.currencySymbol) || this.alwaysDisplayDecimals; }, /** * Display the numeric value with the fixed decimal precision and without the format using the setRawValue, don't need to do a setValue because we don't want a double * formatting and process of the value because beforeBlur perform a getRawValue and then a setValue. */ onFocus: function(){ this.setRawValue(this.removeFormat(this.getRawValue())); this.callParent(arguments); }, processRawValue: function(value) { return this.removeFormat(value); } });
OK, I think I figured out a way to get this to submit the "raw" (i.e. unformatted, numeric-only) value. And I think you were on the right track with processRawValue, brittongr. At least it appears to be working for me. Changes to the source (just the one function override) from the zip file are shown below in bold:
onFocus: function(){ this.setRawValue(this.removeFormat(this.getRawValue())); this.callParent(arguments); }, processRawValue: function(value) { return this.removeFormat(value); }
Ext.define('Teller.ext.CurrencyField', {
extend: 'Ext.form.field.Number',
alias: 'widget.currencyfield',
hideTrigger: true,
setValue: function (v) {
this.callParent(arguments);
if (!Ext.isEmpty(this.getValue())) {
this.setRawValue(Ext.util.Format.currency(this.getValue()));
} }, removeFormat: function (v) {
if (Ext.isEmpty(v)) {
return '';
} else {
v = v.toString().replace(Ext.util.Format.currencySign, '').replace(Ext.util.Format.thousandSeparator, '');
if (v % 1 === 0) { // Return value formatted with no precision since there are no digits after the decimal return Ext.util.Format.number(v, '0'); } else { // Return value formatted with precision of two digits since there are digits after the decimal
return Ext.util.Format.number(v, '0.00'); } } }, // Override parseValue to remove the currency format
parseValue: function (v) { return this.callParent([this.removeFormat(v)]); }, // Remove the format before validating the value getErrors: function (v) {
return this.callParent([this.removeFormat(v)]); }, /* Override getSubmitData to remove the currency format on the value that will be passed out from the getValues method of the form */ getSubmitData: function () { var returnObject = {}; returnObject[this.name] = this.removeFormat(this.callParent(arguments)[this.name]);
return returnObject; }, // Override preFocus to remove the format during edit preFocus: function () {
this.setRawValue(this.removeFormat(this.getRawValue()));
this.callParent(arguments); } });