There is a very nice Answer how to enforce decimal precision in NumberField
: How do I force the display of a decimal in an ExtJS NumberField to a certain precision?.
But it only works half way. I would like to do 1 step more and implement a thousands separator and dollar sign (US Money). I tried to extend baseChars
to '1234567890$,' but it did not work.
Is someone have this already solved or know how to do it?
i just developed yesterday the extension that you are looking for. I needed this kind of features too, and now was the time to finish this.
You can read the post in this blog and download the source there: http://develtech.wordpress.com/2011/03/06/number-field-with-currency-symbol-thousand-separator-with-international-support
or
Visit this thread in the extjs forum http://www.sencha.com/forum/showthread.php?125937-Number-field-with-currency-symbol-thousand-separator-with-international-support&p=577701#post577701
Hope it helps.
/**
* Copyright(c) 2011
*
* Licensed under the terms of the Open Source LGPL 3.0
* http://www.gnu.org/licenses/lgpl.html
* @author Greivin Britton, [email protected]
*
* @changes
* No currency symbol by default
* No decimalPrecision in config
* Supporting any character as thousand separator
* Improved getFormattedValue
* Removed unnecessary code to create format template, now using float.toFixed(this.decimalPrecission)
*/
Ext.ux.NumericField = function(config){
var defaultConfig =
{
style: 'text-align:right;'
};
Ext.ux.NumericField.superclass.constructor.call(this, Ext.apply(defaultConfig, config));
//Only if thousandSeparator doesn't exists is assigned when using decimalSeparator as the same as thousandSeparator
if(this.useThousandSeparator && this.decimalSeparator == ',' && Ext.isEmpty(config.thousandSeparator))
this.thousandSeparator = '.';
else
if(this.allowDecimals && this.thousandSeparator == '.' && Ext.isEmpty(config.decimalSeparator))
this.decimalSeparator = ',';
this.onFocus = this.onFocus.createSequence(this.onFocus);
};
Ext.extend(Ext.ux.NumericField, Ext.form.NumberField,
{
currencySymbol: null,
useThousandSeparator: true,
thousandSeparator: ',',
alwaysDisplayDecimals: false,
setValue: function(v){
Ext.ux.NumericField.superclass.setValue.call(this, v);
this.setRawValue(this.getFormattedValue(this.getValue()));
},
/**
* No more using Ext.util.Format.number, Ext.util.Format.number in ExtJS versions
* less thant 4.0 doesn't allow to use a different thousand separator than "," or "."
* @param {Number} v
*/
getFormattedValue: function(v){
if (Ext.isEmpty(v) || !this.hasFormat())
return v;
else
{
var neg = null;
v = (neg = v < 0) ? v * -1 : v;
v = this.allowDecimals && this.alwaysDisplayDecimals ? v.toFixed(this.decimalPrecision) : v;
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.');
var v = String(v);
var ps = v.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');
v = whole + (ps[1] ? this.decimalSeparator + ps[1] : '');
}
return String.format('{0}{1}{2}', (neg ? '-' : ''), (Ext.isEmpty(this.currencySymbol) ? '' : this.currencySymbol + ' '), v);
}
},
/**
* overrides parseValue to remove the format applied by this class
*/
parseValue: function(v){
//Replace the currency symbol and thousand separator
return Ext.ux.NumericField.superclass.parseValue.call(this, this.removeFormat(v));
},
/**
* Remove only the format added by this class to let the superclass validate with it's rules.
* @param {Object} v
*/
removeFormat: function(v){
if (Ext.isEmpty(v) || !this.hasFormat())
return v;
else
{
v = v.replace(this.currencySymbol + ' ', '');
v = this.useThousandSeparator ? v.replace(new RegExp('[' + this.thousandSeparator + ']', 'g'), '') : v;
//v = this.allowDecimals && this.decimalPrecision > 0 ? v.replace(this.decimalSeparator, '.') : v;
return v;
}
},
/**
* Remove the format before validating the the value.
* @param {Number} v
*/
getErrors: function(v){
return Ext.ux.NumericField.superclass.getErrors.call(this, this.removeFormat(v));
},
hasFormat: function()
{
return this.decimalSeparator != '.' || this.useThousandSeparator == true || !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()));
}
});
Ext.reg('numericfield', Ext.ux.NumericField);
If I understand you correctly, you want to enforce double precission and add a dollar sign. I think it is best adding a renderer to your field:
{
...
fieldLabel: 'amount',
renderer: MyApp.dollarRenderer
}
MyApp.dollarRenderer = function(amount) {
return "$ "+sprintf('%.02f',amount);
}
-> 100.5 becomes $ 100.50
The renderer itself would need a sprintf function (which for god know why is still not natively implemented in Javascript. There is however a nice one I use: http://www.diveintojavascript.com/projects/javascript-sprintf
Adding a thousand separator, change the renderer with this nice regexp:
MyApp.dollarRenderer = function(amount) {
return "$ "+sprintf('%.02f',amount).replace(/\d{1,3}(?=(\d{3})+(?!\d))/g,'$&,');
}
MyApp.dollarRenderer(1298129827.4) -> "$ 1,298,129,827.40"
Good luck
/**
* @author: Frédéric Thomas
* Date: 22/03/12
* Time: 16:37
*/
Ext.define('yourNS.form.field.Currency', {
extend: 'Ext.form.field.Number',
alias: ['widget.currencyField'],
config: {
thousandSeparator: ' ',
currencyAtEnd: true,
currencySign: '€'
},
listeners: {
/**
* When this component get the focus, change the Currency
* representation to a Float one for edition.
*
* @param me
* @param eOpts
*/
focus: function (me, eOpts) {
me.inputEl.dom.value = this.getValue();
}
},
/**
* Converts a Float value into a currency formated value ready to display .
*
* @param {Object} value
* @return {Object} The converted value.
*/
valueToCurrency: function (value) {
var format = Ext.util.Format;
format.currencyPrecision = this.decimalPrecision;
format.thousandSeparator = this.thousandSeparator;
format.currencySign = this.currencySign;
format.currencyAtEnd = true;
return format.currency(value);
},
/**
* Converts a mixed-type value to a raw representation suitable for displaying in the field. This allows controlling
* how value objects passed to {@link #setValue} are shown to the user, including localization.
*
* See {@link #rawToValue} for the opposite conversion.
*
* This implementation converts the raw value to a value formated as currency.
*
* @param {Object} value The mixed-type value to convert to the raw representation.
* @return {Object} The converted raw value.
*/
valueToRaw: function (value) {
return this.valueToCurrency(value);
},
/**
* Performs any necessary manipulation of a raw String value to prepare it for conversion and/or
* {@link #validate validation}. Overrided to apply the {@link #parseValue}
* to the raw value.
*
* @param {String} value The unprocessed string value
* @return {String} The processed string value
*/
processRawValue: function (value) {
return this.parseValue(this.callParent(arguments));
},
/**
* Overrided to remove thousand separator.
*
* @param value
*/
parseValue: function (value) {
value = String(value).replace(this.thousandSeparator, "");
value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
return isNaN(value) ? null : value;
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With