0
function createTextFields(obj) {
    for (var i = 0; i < obj.length; i++) {
        var dataDump = {};
        for (var key in obj[i]) {
            var textField = Ti.UI.createTextField(pm.combine($$.labelBrown, {
            left: 200,
            height:35,
            value:obj[i][key],
            width:550,
            keyboardType:Ti.UI.KEYBOARD_NUMBER_PAD,
            layout:'horizontal',
            backgroundColor:'transparent',
            id:i
         }));

            dataDump[key] = textField.value;
            var callback = function (vbKey) {
                    return function (e) {
                        dataDump[vbKey] = e.source.value;
                    };
                }(key);
        }
        globalData.push(dataDump);
    }

}

I am using the simlar code for Adding the data and it works fine. I posted the problem yesterday and it got resolved...

Last Object is always getting updated?

Now when i go to edit page, it shows me four text fields or number of text fields added... now when i edit something and click on save... the value get's updated on the fourth or the last TextFields Object...

Community
  • 1
  • 1
John Cooper
  • 7,343
  • 31
  • 80
  • 100
  • 1
    Do you still have the problem if you move all your `var` declarations to the top of the function? So make the first line of the funtion `var i, dataDump, key, callback;` and remove all the `var` keywords throughout the function? – DaveRandom Aug 18 '11 at 09:36
  • You're defining `callback` and assigning it a function but you are not using that variable anywhere or am I missing something here? – nobody Aug 18 '11 at 09:58
  • @DaveRandom: It did not solve the issue, the data is again getting saved to last object... – John Cooper Aug 18 '11 at 10:10

2 Answers2

1

Don't define functions inside loops. Computationally expensive and leads to problems, like this one. Here's a fix that should solve it:

function createTextFields(obj) {

     var callback = function (vbKey, localDump) {
                    return function (e) {
                        localDump[vbKey] = e.source.value;
                    };
                }
    var i;
    var max = obj.length;
    for (i = 0; i < max; i++) {
        var dataDump = {};
        for (var key in obj[i]) {
            dataDump[key] = textField.value;
            var callBackInstance = function(keyn, dataDump);
         }
        globalData.push(dataDump);
    }

}
Matthew
  • 12,892
  • 6
  • 42
  • 45
  • And don't evaluate `obj.length` inside of loops – Nemoden Aug 18 '11 at 09:41
  • @Nemoden Why not (not saying you should, just wondering why not to)? And also, what is the deal with this callback function - it doesn't seem to be used anywhere, just being redefined over and over... – DaveRandom Aug 18 '11 at 09:43
  • I had the same question myself @DaveRandom (about the callback function) I sort of assumed that it was stubbed out code. (Because where is the textfield coming from for that matter) – Matthew Aug 18 '11 at 09:48
  • @DaveRandom because `obj.length` evaluation is pretty heavy operation on DOM elements. I think `obj` here is a `HTMLCollection` retreived by `getElementsByName` or `getElementsByTagName` etc, so it's better cache `obj.length` like `var i=0, max = obj.length; for (;i – Nemoden Aug 18 '11 at 09:50
  • @Nemoden fair enough, I thought you were saying you had some other magic way of iterating through the properties of an object! I take your point though, and I will definitely try and write like that in future - I must have written hundreds of `for (i = 0; i < e.length; i++)`s in my time... – DaveRandom Aug 18 '11 at 09:57
  • @Mathew: It did not solve the issue, the data is again getting saved to last object... – John Cooper Aug 18 '11 at 10:05
  • Hm from what I saw it looked like you weren't binding the dataDump var. I need a little more context then, where is the textfield var coming from and where are you adding the callback (post a little more code) – Matthew Aug 18 '11 at 10:14
  • @Mathew: for (var key in obj[i]) { var textField; dataDump[key] = textField.value; var callBackInstance = function (keyn dataDump); } – John Cooper Aug 18 '11 at 10:15
  • @Mathew: As of now i am adding callBack after the function createTextField and before the first iteration – John Cooper Aug 18 '11 at 10:17
  • @Mathew: Here is a complete pastie.. http://pastie.org/private/0f08i6ef4asshymngeqqq – John Cooper Aug 18 '11 at 10:23
  • @John Cooper hmm that sounds pretty fishy. Can you put up that code specifically (the part where you are calling createTextField) – Matthew Aug 18 '11 at 10:25
  • @John Cooper in the pastie the code doesn't quite match what i have there. Not positive this is it but look carefully at the variable name used inside callback, should be localDump, you have dataDump – Matthew Aug 18 '11 at 10:33
  • @Matthew let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/2609/discussion-between-john-cooper-and-matthew) – John Cooper Aug 18 '11 at 10:36
1

JavaScript does not have block level scope, so your variables dataDump and callback, though "declared" inside for-loops actually belong to the function. As in, you're saving a value to dataDump, then you're overwriting it, each time you go through the loop. Which is why finally only the code that operated on the last value remains.

Take a look at What is the scope of variables in JavaScript? too.

Community
  • 1
  • 1
Roshan Mathews
  • 5,788
  • 2
  • 26
  • 36