Javascript class variable scope

I am kind of wrestling with Javascript variable scopes combined with JQuery JSON call. Unforutnatly, I cannot post this script to jsFiddle because it needs some data.

I am trying to dynamically load data and display it to the user's screen. Now I have created a method that loads data for the first time. Later, I would like to make an update method that updates the data in the rows of the table.

But now I have a problem with variable scope. When $ .pcw.outstandingInvoices.init () is called, I get the following error:

ypeError: can't convert undefined to object
this.outstandingInvoicesArray[key] = entry;

      

My code:

-- Post is getting to long, so removed the first code i've used. -- 

      

Can anyone tell me what I am doing wrong so I can fix it?

Thanks in advance!

--- UPDATE --- I edited what you told me, but still I get errors ... Can anyone tell me what I am doing wrong?

My new code and errors:

-- Post is getting to long, so removed the first update of the code. -- 

      

Errors:

Initializing outstandingInvoices class.
Loading outstanding invoices from server.

TypeError: context.outstandingInvoicesObject is undefined
if (context.outstandingInvoicesObject.length == 0) {

TypeError: can't convert undefined to object
self.outstandingInvoicesObject[key] = entry;

      

- UPDATE 2 - Just edited my code and now I don't get any error, but the data in the outstandingInvoicesObject is not stored correctly, so the addOutstandingInvoicesTable method cannot find any invoices. I was analyzing the console and it looks like there is something wrong with the order of execution of the methods ...

Code:

$.pcw.outstandingInvoices = function () {
    var context = this;
    context.outstandingInvoicesObject = [];

    context.init = function ()
    {
        console.log('Initializing outstandingInvoices class.');

        context.loadData();        
        context.removeLoader();
        context.addOutstandingInvoicesToTable();
    };

    context.loadData = function ()
    {
        console.log('Loading outstanding invoices from server.');

        jQuery.getJSON('/ajax/outgoing-invoices/find-outstanding.json', function (data)
        {   
            var i = 0;
            jQuery.each(data, function (key, entry)
            {
                context.outstandingInvoicesObject[key] = entry;

                ++i;
            });

            console.log('Loaded ' + i + ' invoices');
        }).error(function () {
            console.error('Error while loading outstanding invoices.');
        });
    };

    context.removeLoader = function ()
    {
        console.log('Removing loader');

        jQuery('table#invoices-outstanding tr.ajax-loader').fadeOut();
    };

    context.addOutstandingInvoicesToTable = function()
    {
        console.log('Outputing invoices to table');

        if (context.outstandingInvoicesObject.length == 0) {
            console.log('No outstanding invoices found');
        }

        jQuery.each(context.outstandingInvoicesObject, function (key, entry)
        {
            // This is a new outstanding invoice
            var rowClass = 'info';

            switch(entry.status)
            {
                case 'Created':
                case 'Sent':
                case 'Paid': // The invoices with Paid statuses aren't show here, because we only show the oustanding invoices on this page.
                    rowClass = 'success';
                break;

                case 'First reminder':
                case 'Second reminder':
                case 'Partially paid':
                    rowClass = 'warning';
                break;

                case 'Third reminder':
                case 'Collection agency':
                case 'Judicial proceedings':
                    rowClass = 'error';
                break;
            }

            jQuery('table#invoices-outstanding tbody').append(
                outstandingInvoice = jQuery('<tr/>', {
                    id: 'outgoing-invoice-' + key,
                    class: rowClass
                }).append(
                    jQuery('<td/>', {
                        class: 'id',
                        text: key
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'debtor-name',
                        text: entry.debtor_name
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'amount',
                        text: entry.amount
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'date',
                        text: entry.created_timestamp
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'status',
                        text: entry.status
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'creator',
                        text: entry.creator
                    })
                )            
            );
        });
    }
}


// When document is ready
(function()
{
    var invoices = new $.pcw.outstandingInvoices();
    invoices.init();
})();

      

Console output:

Initializing outstandingInvoices class.

Loading outstanding invoices from server.
GET /ajax/outgoing-invoices/find-outstanding.json
200 OK
509ms   

Removing loader

Outputing invoices to table

No outstanding invoices found

Loaded 29 invoices

      

thank

+3


source to share


5 answers


The problems have now been resolved. It was a combination of what you guys told and the problem was that the AJAX call was asynchronous.

Final working code:



$.pcw.outstandingInvoices = function () {
    var context = this;
    context.outstandingInvoicesObject = new Object();

    context.init = function ()
    {
        console.log('Initializing outstandingInvoices class.');

        context.loadData();                
        context.removeLoader();
        context.addOutstandingInvoicesToTable();
    };

    context.loadData = function ()
    {
        console.log('Loading outstanding invoices from server.');

        $.ajax({
            url: '/ajax/outgoing-invoices/find-outstanding.json',
            dataType: 'json',
            async: false,
            success: function(data) {                
                var i = 0;            
                jQuery.each(data, function (invoiceId, invoiceDetails)
                {
                    context.outstandingInvoicesObject[invoiceId] = invoiceDetails;

                    ++i;                                
                });

                console.log('Loaded ' + i + ' invoices');       
            }
        }).error(function () {
            console.error('Error while loading outstanding invoices.');
        });
    };

    context.removeLoader = function ()
    {
        console.log('Removing loader');

        jQuery('table#invoices-outstanding tr.ajax-loader').fadeOut();
    };

    context.addOutstandingInvoicesToTable = function()
    {
        console.log('Outputing invoices to table');           

        if (context.outstandingInvoicesObject.length == 0) {
            console.log('No outstanding invoices found');            
        }

        jQuery.each(context.outstandingInvoicesObject, function (key, entry)
        {
            // This is a new outstanding invoice
            var rowClass = 'info';

            switch(entry.status)
            {
                case 'Created':
                case 'Sent':
                case 'Paid': // The invoices with Paid statuses aren't show here, because we only show the oustanding invoices on this page.
                    rowClass = 'success';
                break;

                case 'First reminder':
                case 'Second reminder':
                case 'Partially paid':
                    rowClass = 'warning';
                break;

                case 'Third reminder':
                case 'Collection agency':
                case 'Judicial proceedings':
                    rowClass = 'error';
                break;
            }

            jQuery('table#invoices-outstanding tbody').append(
                outstandingInvoice = jQuery('<tr/>', {
                    id: 'outgoing-invoice-' + key,
                    class: rowClass
                }).append(
                    jQuery('<td/>', {
                        class: 'id',
                        text: key
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'debtor-name',
                        text: entry.debtor_name
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'amount',
                        text: entry.amount
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'date',
                        text: entry.created_timestamp
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'status',
                        text: entry.status
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'creator',
                        text: entry.creator
                    })
                )            
            );
        });
    }
}

// When document is ready
(function()
{   
    var invoices = new $.pcw.outstandingInvoices();
    invoices.init();
})();

      

Thanks for the help guys!

0


source


Make a backup copy of the object so that you can use it in functions that this

do not reference the object.



loadData: function ()
{
    console.log('Loading outstanding invoices from server.');
    var self = this;
    jQuery.getJSON('/ajax/outgoing-invoices/find-outstanding.json', function (data)
    {            
        jQuery.each(data, function (key, entry)
        {
            self.outstandingInvoicesArray[key] = entry;
        });
    }).error(function () {
        console.error('Error while loading outstanding invoices.');
    });
},

      

+1


source


You are creating outstandingInvoicesArray

as an array, but you are trying to access it as an object:

outstandingInvoicesArray: []
[...]
this.outstandingInvoicesArray[key] = entry;

      

create it as an object:

outstandingInvoicesArray: {}

      

+1


source


You must use the new keyword when initializing the object if you want to use it:

$.pcw.outstandingInvoices = function(){
   var context = this;//replace every instance of "this" in your class with the context var

   context.init= function ()
    {
        console.log('Initializing outstandingInvoices class.');

        context.loadData();

    }
    //the rest of functions defined below
}
var invoices = new $.pcw.outstandingInvoices();
invoices.init();

      

Edit: To fix the remaining bugs, try using context instead of self and declare a prominentInvoicesObject in the context:

$.pcw.outstandingInvoices = function () {
    var context = this;
    context.outstandingInvoicesObject = [];

    context.init = function ()
    {
        console.log('Initializing outstandingInvoices class.');

        context.loadData();

    };

    context.loadData = function ()
    {
        console.log('Loading outstanding invoices from server.');



        jQuery.getJSON('/ajax/outgoing-invoices/find-outstanding.json', function (data)
        {            
            jQuery.each(data, function (key, entry)
            {
                context.outstandingInvoicesObject[key] = entry;
            });
            //now that we have data, call add the invoices to the table
            context.removeLoader();
            context.addOutstandingInvoicesToTable();
        }).error(function () {
            console.error('Error while loading outstanding invoices.');
        });
    };

    context.removeLoader = function ()
    {
        jQuery('table#invoices-outstanding tr.ajax-loader').fadeOut();
    };

    context.addOutstandingInvoicesToTable = function()
    {
        if (context.outstandingInvoicesObject.length == 0) {
            console.log('No outstanding invoices found');
        }

        jQuery.each(context.outstandingInvoicesObject, function (key, entry)
        {
            // This is a new outstanding invoice
            var rowClass = 'info';

            switch(entry.status)
            {
                case 'Created':
                case 'Sent':
                case 'Paid': // The invoices with Paid statuses aren't show here, because we only show the oustanding invoices on this page.
                    rowClass = 'success';
                break;

                case 'First reminder':
                case 'Second reminder':
                case 'Partially paid':
                    rowClass = 'warning';
                break;

                case 'Third reminder':
                case 'Collection agency':
                case 'Judicial proceedings':
                    rowClass = 'error';
                break;
            }

            jQuery('table#invoices-outstanding tbody').append(
                outstandingInvoice = jQuery('<tr/>', {
                    id: 'outgoing-invoice-' + key,
                    class: rowClass
                }).append(
                    jQuery('<td/>', {
                        class: 'id',
                        text: key
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'debtor-name',
                        text: entry.debtor_name
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'amount',
                        text: entry.amount
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'date',
                        text: entry.created_timestamp
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'status',
                        text: entry.status
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'creator',
                        text: entry.creator
                    })
                )            
            );
        });
    }
}

      

+1


source


The following should fix your problems. You didn't declare oustandingInvoicesObject the way you intended. In your case, this should be detached from 'this' or "context".

Additionally, you declared oustandingInvoicesObject to be an array instead of an object. You cannot add properties to an array like an object.

Let me know how it goes.

$.pcw.outstandingInvoices = function () {
    var context = this;
    context.outstandingInvoicesObject = {};

    context.init = function ()
    {
        console.log('Initializing outstandingInvoices class.');

        context.loadData();
        context.removeLoader();
        context.addOutstandingInvoicesToTable();
    };

    context.loadData = function ()
    {
        console.log('Loading outstanding invoices from server.');

        var self = this;

        jQuery.getJSON('/ajax/outgoing-invoices/find-outstanding.json', function (data)
        {            
            jQuery.each(data, function (key, entry)
            {
                self.outstandingInvoicesObject[key] = entry;
            });
        }).error(function () {
            console.error('Error while loading outstanding invoices.');
        });
    };

    context.removeLoader = function ()
    {
        jQuery('table#invoices-outstanding tr.ajax-loader').fadeOut();
    };

    context.addOutstandingInvoicesToTable = function()
    {
        if (context.outstandingInvoicesObject.length == 0) {
            console.log('No outstanding invoices found');
        }

        jQuery.each(context.outstandingInvoicesObject, function (key, entry)
        {
            // This is a new outstanding invoice
            var rowClass = 'info';

            switch(entry.status)
            {
                case 'Created':
                case 'Sent':
                case 'Paid': // The invoices with Paid statuses aren't show here, because we only show the oustanding invoices on this page.
                    rowClass = 'success';
                break;

                case 'First reminder':
                case 'Second reminder':
                case 'Partially paid':
                    rowClass = 'warning';
                break;

                case 'Third reminder':
                case 'Collection agency':
                case 'Judicial proceedings':
                    rowClass = 'error';
                break;
            }

            jQuery('table#invoices-outstanding tbody').append(
                outstandingInvoice = jQuery('<tr/>', {
                    id: 'outgoing-invoice-' + key,
                    class: rowClass
                }).append(
                    jQuery('<td/>', {
                        class: 'id',
                        text: key
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'debtor-name',
                        text: entry.debtor_name
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'amount',
                        text: entry.amount
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'date',
                        text: entry.created_timestamp
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'status',
                        text: entry.status
                    })
                ).append(
                    jQuery('<td/>', {
                        class: 'creator',
                        text: entry.creator
                    })
                )            
            );
        });
    };
};

// When document is ready
(function(){
    var invoices = new $.pcw.outstandingInvoices();
    invoices.init();
})();

      

+1


source







All Articles