6

Below is a snippet of my code. The error I am getting is that when I perform a search and call the method _searchData, it successfully calls the method _lookUpSuccess, however then returns the following error:

JavaScript runtime error: Unable to get property '_displayResult' of undefined or null reference

when it tries to call the _displayResult method.

Why this may be?

(function () {

    // make this an object property/method eventually
    var displayResult = function (queryResult) {
        for (var i = 0; i < holder.length; i++) {
            //document.querySelector(".item-content .title").textContent = "FilmApp";
            document.querySelector(holder[i]).textContent = queryResult[i];
       }};

    // Creates a new page control with members
    ui.Pages.define(searchPageURI, {
       //...
        _searchData: function (queryText) {
            searchBase          = 'http://www.example.com/web-service2.php?termID=';
            searchFormat        = 'JSON';
            searchFormatPiece   = '&format=' + searchFormat;

            if (!window.Data) {  
                var searchUrl = searchBase + queryText + searchFormatPiece;
                WinJS.xhr({ url: searchUrl }).done(this._lookUpSuccess, this._lookUpFail, this._lookUpProgress);
            }else{
                document.querySelector(".titlearea .pagetitle").textContent = "There has been a computer malfunction - sort it the **** out!";
            }
        },

        _lookUpSuccess: function xhrSucceed(Result) {
            var response = JSON.parse(Result.responseText);
                if (response.response[0].Message === "Found") {
                    for (var x in response.response[1].term) {
                        content.push(response.response[1].term[x]);
                    };
                    this._displayResult(content);
                    //displayResult(content);
                    return content;
                } else {
                    content.push("Not Found", "Not Found");
                    return content;
                }
         },

        _lookUpFail: function xhrFail(Result) { document.querySelector(".titlearea .pagetitle").textContent = "Got Error"; },
        _lookUpProgress: function xhrProgress(Result) { document.querySelector(".titlearea .pagetitle").textContent = "No Result 2"; },

        _displayResult: function (queryResult) {
            var holder;
            holder = [DefDiv, DescDiv];

            for (var i = 0; i < holder.length; i++) {
                //document.querySelector(".item-content .title").textContent = "FilmApp";
                document.querySelector(holder[i]).textContent = queryResult[i];
            };
        },

    });

    // End of UI.page.define    

    // #2 This method is run on application load
    WinJS.Application.addEventListener("activated", function (args) {
        if (args.detail.kind === appModel.Activation.ActivationKind.search) {
            args.setPromise(ui.processAll().then(function () {
                if (!nav.location) {
                    nav.history.current = { location: Application.navigator.home, initialState: {} };
                }
            return nav.navigate(searchPageURI, { queryText: args.detail.queryText });
            }));
        }
    });

    // #3 
    appModel.Search.SearchPane.getForCurrentView().onquerysubmitted = function (args) { nav.navigate(searchPageURI, args); };

})();
Kenster
  • 23,465
  • 21
  • 80
  • 106
James
  • 737
  • 2
  • 11
  • 27

2 Answers2

8

In this line of code:

WinJS.xhr({ url: searchUrl }).done(this._lookUpSuccess, this._lookUpFail, this._lookUpProgress);

You are passing _lookupSuccess as the done handler function, but when it is called, the value of this is no longer what you want it to be because that will be set by the internals of whatever calls the done handler. Passing this._lookUpSuccess as the function just passes the function. It doesn't pass the value of this. So, when this._lookUpSuccess is called with the wrong this, any references to this inside of it will not find the expected properties on it (thus the error you see).

You can fix it like this which saves the this value in a local variable and then use it when calling _lookUpSuccess():

var self = this;
WinJS.xhr({ url: searchUrl }).done(function(result) {self._lookUpSuccess(result)}, this._lookUpFail, this._lookUpProgress);

This is a very common work-around for reattaching the proper this value in callbacks.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks very much, this has worked, however it has introduced a new problem in the `lookUpSuccess` method. Now I get ` Unable to get property 'responseText' of undefined or null reference` as if making that amendment has stopped any values being passed to `_lookUpSuccess` – James Jan 08 '13 at 08:24
  • @James - yes, you have to pass along the result value. I've modified my answer to show how you do that. Note: you have have the exact same issue with `_lookUpFail` and `_lookUpProgress` if they need the `this` ptr. – jfriend00 Jan 08 '13 at 08:58
  • This worked perfectly, thanks very much for this help. A very useful bit of troubleshooting to know! – James Jan 08 '13 at 09:59
  • Thank you very much! This solved a problem I had been stuck on for the past hour. :D – varagrawal Aug 23 '13 at 14:58
2

In:

this._displayResult(content);

There, this is apparently undefined or null

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • I thought this originally but then saw the following link which suggested it should be `undefined` - http://stackoverflow.com/questions/9822561/why-is-this-in-an-anonymous-function-undefined-when-using-strict – James Jan 08 '13 at 08:20