0

Alright so I'm working on some legacy code pretty much only using Jquery and I am stumped.

from what I gather we start at the newView = new DOMObj(). where vm.products is initialized.

the next step is the data call which has a for worker that iterates through the JSON and assigns it's objects in vm.products.

the next call is updateItemHTML which does another iteration and populates a template with values(I can't believe people had to do this back in the day)

Finally, the last function we call is updateWindow which is supposed to create one large html template and append it to the body.

Problem I'm hitting is that vm.items[].htmlView is undefined for some reason. I can't tell if its a Jquery thing or if I'm missing a crucial step but any help is appreciated.

It's gotta be somewhere in either the itemObj() or the vm.updateDOM()

 function DOMObj(){
    var vm = this;

    vm.items = [];

    vm.getItems = function(url) {

        $.getJSON(url, function(response) {
            for(var i = 0; i < response.sales.length; i++){

                vm.items.push(new itemObj(response.sales[i], i));

            }
        });

    };

    vm.updateItemHTML = function(){
        for( var i = 0; i < vm.items.length; i++){

            vm.items[i].updateHTML();

        }

    };

    vm.updateWindow = function() {

        var thisHTML = '';

        for( var i = 0; i < vm.items.length; i++){

            if (i % 3 === 0 ) {
                thisHTML += "<div class='row'>";
            }

            thisHTML += vm.items[i].htmlView;

            if ((i % 3 === 2) || i === (vm.items.length - 1) ){
                thisHTML += "</div>";
            }
        }
        $("#content").append(thisHTML);
    }
}

function itemObj(item, i) {
    var vm = this;

    vm.picture = item.photo;
    vm.title = item.name;
    vm.tagline = item.tagline;
    vm.url = item.url;

    vm.htmlView = "";
    vm.index = i;

    vm.class = "col" + ( (i % 3) + 1);

    vm.updateHTML = function() {
        $.get('item-template.html', function(template){
            vm.htmlView = template.replace('{image}', vm.photo)
                .replace('{string1}', vm.title)
                .replace('{string2}', vm.tagline)
                .replace('{URL}', vm.url)
                .replace('{class}', vm.class);
        });
    };
}
var newView = new DOMObj();


        newView.getItems('data.json');


            newView.updateItemHTML();
            newView.updateWindow();

I have cut it up a bit (omitting some things that aren't necessary) as I'm always paranoid so if a variable is misspelled or something it probably isn't the problem but I appreciate pointing those out too.

*keep in mind that the last 4 functions don't work in this instance but pretend that the dataCall executes before the itemUpdates and DOM updates

All I know is that I really appreciate what frameworks do for me.

--UPDATE --

ah I figured eventually omitting some of the code would be an issue

// execute promise chain

mainPromise()
    .then(getData);

//the timeout is a little hack to ensure the sequence is correct
mainPromise()
    .then(() => {
        setTimeout(() => {
            newView.updateItemHTML();
        }, 0);

        setTimeout(() => {
            newView.updateWindow();
        }, 0);
    });

added omitted code

Rob Cha
  • 139
  • 12
  • May be `updateItemHTML()` and `updateWindow()` are called even before items are pushed into `vm.items`. Are you able to put `updateItemHTML()` inside `success` of the `$.getJSON` and `updateWindow()` inside `updateItemHTML` after the `for` loop see if that helps ? – Searching Nov 02 '16 at 02:17
  • I think the problem comes from `this` in `itemObj` function. Are you sure what `this` refer to is really what you want? – Jason Xu Nov 02 '16 at 02:28
  • @Searching No dice, from debug I can see that the array is populated with the exception of the htmlView. – Rob Cha Nov 02 '16 at 02:31

1 Answers1

0

vm.getItems does a http request which is asynchronous.

newView.updateItemHTML is called instantly without waiting for the callback handler to be executed.

You need need to pass in a callback function to execute once the http request is finished.

vm.getItems = function(url, callback)

and call it

$.getJSON(url, function(response) {
    for(var i = 0; i < response.sales.length; i++){

        vm.items.push(new itemObj(response.sales[i], i));

    }
    if (callback) {
        callback();
    }
});

And pass it in like

newView.getItems('data.json', function() {
    newView.updateItemHTML();
    newView.updateWindow();
});
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • I used promises to try and avoid that. I've been running through the async call all day, I wonder if I missed something with it. I added that code to the Q. – Rob Cha Nov 02 '16 at 03:06