PDA

View Full Version : [FIXED] Spinner Bug



jongohr
7 Sep 2011, 4:28 AM
Touch 1.1.0

Have a spinner configured like this.


new Ext.form.Spinner({
name: 'alpha',
label: 'Level',
minValue: .2,
maxValue: 4.0,
incrementValue: .1,
value: 1.0,
cycle: true
})

First click of the '+' button increments to 1.1 and the next click of the '+' button increments to 1.2000000000000002

mitchellsimoens
7 Sep 2011, 8:17 AM
I typed this in the Chrome WebKit Inspector:


1.1 + 0.1

And it echoed 1.200000000002 so it appears that this isn't a Sencha Touch bug but something that may need to be looked in to. Possibly need a format config like in Ext JS which would be a workaround.

mitchellsimoens
7 Sep 2011, 8:29 AM
Found out that this is a JS thing using IEEE numbers which is why there are lots of "noise" in the value. The value is technically correct but not what is expected.

mitchellsimoens
7 Sep 2011, 11:17 AM
Not sure if this is going to be what we will do (or if we do anything :) ).

Ext JS 3 has a number method on Ext.util.Format so I ported that over:


Ext.util.Format.number = function(v, format) {
if (!format) {
return v;
}
v = Ext.num(v, NaN);
if (isNaN(v)) {
return '';
}
var comma = ',',
dec = '.',
i18n = false,
neg = v < 0;

v = Math.abs(v);
if (format.substr(format.length - 2) == '/i') {
format = format.substr(0, format.length - 2);
i18n = true;
comma = '.';
dec = ',';
}

var hasComma = format.indexOf(comma) != -1,
psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);

if (1 < psplit.length) {
v = v.toFixed(psplit[1].length);
} else if(2 < psplit.length) {
throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
} else {
v = v.toFixed(0);
}

var fnum = v.toString();

psplit = fnum.split('.');

if (hasComma) {
var cnum = psplit[0],
parr = [],
j = cnum.length,
m = Math.floor(j / 3),
n = cnum.length % 3 || 3,
i;

for (i = 0; i < j; i += n) {
if (i != 0) {
n = 3;
}

parr[parr.length] = cnum.substr(i, n);
m -= 1;
}
fnum = parr.join(comma);
if (psplit[1]) {
fnum += dec + psplit[1];
}
} else {
if (psplit[1]) {
fnum = psplit[0] + dec + psplit[1];
}
}

return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
};

So I am setting up the Spinner field like this (important line in red & bold):


var form = new Ext.form.FormPanel({
fullscreen : true,
items : [
{
xtype : 'spinnerfield',
label : 'Test',
minValue : 0.2,
maxValue : 4,
incrementValue : 0.1,
value : 1,
format : '0.0',
cycle : true
}
]
});

So now to bring it altogether, here is the actual override to get this to work:


Ext.form.Spinner.override({
setValue : function(value) {
value = parseFloat(value);

var format = this.format;

if (format) {
value = Ext.util.Format.number(value, format);
}

if (isNaN(value)) {
value = this.defaultValue;
}

Ext.form.Number.prototype.setValue.call(this, value);
}
});

Let me know if this works for you :) For docs on different formats to use in Ext.util.Format.number, look at the Ext JS 3.x API docs: http://dev.sencha.com/deploy/ext-3.4.0/docs/?class=Ext.util.Format

vitorgomes
13 Sep 2011, 10:27 PM
Hi Mitchell,

I was having the same problem.
I added the code to my app.js and it's working pretty well.

Thanks!
Vitor

mitchellsimoens
14 Sep 2011, 4:47 AM
Hi Mitchell,

I was having the same problem.
I added the code to my app.js and it's working pretty well.

Thanks!
Vitor

Fantastic!

khilton
14 May 2013, 10:06 PM
The thread says this is fixed in Touch 2.0. Correct me if I'm wrong, but this looks to be not working again in Architect. (I'm using Architect 2.1.0 build 678).

There isn't a property "Format" to set. The online docs don't show an Ext.util.Format.number.

But if there's a simpler way than how I did it I'd be pleased to hear it. In the meantime, this is how I got it to work...

First, the Ext.util.Format.number code that Mitchell provided worked perfectly. The override, though, didn't quite work out of the box. There is another method that takes place "applyValue" that unfortunately takes the perfectly formatted number and changes it to 1 decimal (as in 0.0).

Here's what I did in Architect.

I changed the override code to the following:



Ext.form.Spinner.override({
applyValue : null,
setValue : function(value) {
value = parseFloat(value);


var format = this.config.format;

//Moved this above the if(format) so the default value gets formatted properly also
if (isNaN(value) || value === null) {
value = this.defaultValue;
}


if (format) {
value = Ext.util.Format.number(value, format);
}


// Ext.form.Number.prototype.setValue.call(this, value);
return this.callParent([value]);
}
});


I placed the formatting code from Mitchell and the code above into a .js file and added it as a resource in Architect. Then I had to create an override in Architect for the spinner in order to add the "format : '0.00'" that Mitchell described.

That's it. It did what I need. FYI, the same thing works for a number field also. Just change the

Ext.form.Spinner.override({

to

Ext.field.Number.override({

Again, if there's a better way, please let me know. Otherwise, I hope this saves someone a little time.