2

In the code below I am calling loadAuthorsList function which should then pass its information on to the loadTemplate function. But I am being told by firebug that 'this.loadTemplate' is not a function. Why and how do I fix it?

 var LI = {
        sFI: x,
     loadAuthorsList: function () {
            myApp.showPleaseWait();
            //for later
            $('#records_table').find('tr:gt(0)').remove();
            jQuery.ajax({
                url: this.sFI.getServiceRoot('A'),
                type: 'POST',
                dataType: 'json',
                data: {},
                beforeSend: this.sFI.setModuleHeaders,
                success: function (data) {
                    this.loadTemplate('AuthorTemplate', '#author_records', data)
                },
                complete: function () {

                }
            });
        },

    loadTemplate: function (templateName, selectorName, inputData) {
            var jsPath = this.serviceFrameInstructors.getServiceRoot('LearnoogleInstructors');
            jQuery.ajax({
                url: jsPath.slice(0, -4) + 'js/templates/' + templateName + '.html',// + intArea,
                cache: false,
                success: function (value) {
                    var personTemplate = $.templates(value);
                    var html = personTemplate.render(inputData);
                    $(selectorName).html(html);
                }
            });
        }
    };
braindice
  • 988
  • 5
  • 16

1 Answers1

2

Because in success callback this points to another object (XHR). You can bind context explicitly with Function.prototype.bind for example:

success: function (data) {
    this.loadTemplate('AuthorTemplate', '#author_records', data)
}.bind(this),

Or simpler, you can store reference to correct context in variable:

var self = this;
jQuery.ajax({
    url: this.sFI.getServiceRoot('A'),
    type: 'POST',
    dataType: 'json',
    data: {},
    beforeSend: this.sFI.setModuleHeaders,
    success: function (data) {
        self.loadTemplate('AuthorTemplate', '#author_records', data)
    },
    complete: function () {

    }
});

Or one more options: use can use jQuery context setting to provide context for AJAX callbacks:

context: this,
success: function (data) {
    this.loadTemplate('AuthorTemplate', '#author_records', data)
},
dfsq
  • 191,768
  • 25
  • 236
  • 258
  • is this a good way to do this? – braindice Jun 11 '15 at 15:49
  • @braindice - it's convention in JS to solve this simple, commonly encountered circumstance. – Adam Jenkins Jun 11 '15 at 15:52
  • @braindice I'd recommend that you use bind. This page will teach you all about it as well as the intricacies of function calling within JavaScript https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind – Olical Jun 11 '15 at 15:52
  • `Function.prototype.bind` is not supported by IE8<. See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind – Raul Fernandez Jun 11 '15 at 15:52
  • @RaulFernandez And for IE8 there is `$.proxy`. But better to use `context: this` setting. I would go with `bind` or self. – dfsq Jun 11 '15 at 15:53
  • 1
    @RaulFernandez - that's why `self` is the common convention. But depending on what environment you need to support, `bind` is perfectly fine as well. – Adam Jenkins Jun 11 '15 at 15:53