Use Renderer for ExtJS Form Field
I am trying to create a PercentField component that extends textfield
for use in ExtJS forms. The behavior I'm looking for is a field to display percentage values, eg. 25%
or 400%
, but have a basic meaning when the user is editing the field or the form is represented as decimal, for example. .25
or 4
.
I managed to get this working using a renderer on a grid column, ( fiddle here) , but it doesn't look like it textfield
has a renderer property for using a field in basic forms. I've looked at the methods rawToValue
and valueToRaw
, but they don't seem to be exactly what I'm looking for. Any advice?
source to share
As far as I know, there is no template option for form fields. This would require flipping the input element and displaying a div or whatever, focusing and blurring. It would be doable, but it does involve some finely tuned CSS.
An easier option is to implement custom methods valueToRaw
and rawToValue
, while Ext handles the value lifecycle (this is the really tricky part). You will still have to change the original value to focus and blur, but it remains pretty simple.
Here's an example you can build on (see fiddle ):
Ext.define('My.PercentTextField', {
extend: 'Ext.form.field.Text',
onFocus: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.rawToValue(v));
}
},
onBlur: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.valueToRaw(v));
}
},
valueToRaw: function(v) {
return Ext.isEmpty(v)
? ''
: v * 100 + ' %';
},
rawToValue: function(v) {
// cast to float
if (!Ext.isEmpty(v)) {
var pcRe = /^(\d*(?:\.\d*)?)\s*%$/,
dcRe = /^\d*(?:\.\d*)?$/,
precision = 2,
floatValue,
match;
if (match = dcRe.test(v)) { // decimal input, eg. .33
floatValue = v * 1;
} else if (match = pcRe.exec(v)) { // % input, eg. 33 %
floatValue = match[1] / 100;
} else {
// invalid input
return undefined;
}
floatValue = Number.parseFloat(floatValue);
if (isNaN(floatValue)) {
return undefined;
} else {
return floatValue.toFixed(precision);
}
} else {
return undefined;
}
}
});
source to share