0

I'm using Bing maps v8 to do geocoding. at first this code was not in a class. I've ended up adding the code in a class, because of this error:

typescript cannot redeclare block-scoped variable 'map'

Because I'm using a class now I'm having problems with 'this.'. After reading about 'this' in TypeScript, I've changed my functions using Instance functions (instance arrow functions):

/// <reference path="./../scripts/MicrosoftMaps/Microsoft.Maps.d.ts" />
/// <reference path="./../scripts/MicrosoftMaps/Modules/Search.d.ts" />
/// <reference path="./../scripts/typings/jquery/jquery.d.ts" />

class BMGeocode {

    map: Microsoft.Maps.Map;
    searchManager: Microsoft.Maps.Search.SearchManager;

    public loadMap = () => {
        this.map = new Microsoft.Maps.Map('#map', {
            credentials: 'xxx',
            center: new Microsoft.Maps.Location(51.087299, 2.976770),
            zoom: 10
        });
    }

    public search = () => {
        if (!this.searchManager) {
            Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
                this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map) ; // PROBLEM: searchManager is never set?
            });
        }

        // remove any previous results from the map.
        this.map.entities.clear();

        // get the users query and geocode it.
        let query: string = (<HTMLInputElement>document.getElementById("txtInput")).value;
        this.geocodeQuery(query);
    }

    private geocodeQuery = (query: string) => {
        var userData = { name: 'Maps Test User', id: 'XYZ' };
        let searchRequest: Microsoft.Maps.Search.IGeocodeRequestOptions = {
            where: query,
            userData: userData,
            count: 5,
            bounds: this.map.getBounds(),
            callback: function (r: any) {
                // PROBLEM: r undefined.
                if (r && r.results && r.results.length > 0) {
                    var topResult = r.results[0];
                    if (topResult) {
                        this.addPin(topResult.location);
                        $('#txtInput').focus().select();
                    }
                }
            },
            errorCallback: function (e: any) {
                // If there is an error, alert the user about it.
                alert("No results found.");
            }
        };

        // make the geocode request:
        this.searchManager.geocode(searchRequest);
    }

    // .. other stuff in class
}


let geo: BMGeocode = new BMGeocode();

function onGeocodeClick() {
    geo.search();
}

$(function() {
    geo.loadMap();
    $('#geocode').click(onGeocodeClick);
})

I think I've detected the problem why it doesn't work, as the searchManager is always null or undefined. However I don't know how to solve it.

This line from the 'search' function works but doesn't seem to set the searchManager variable:

this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map);

the searchManager is not set, so I can't make a request:

// make the geocode request:
    this.searchManager.geocode(searchRequest);

How can this be solved in TypeScript?

Update: this doesn't seem to work either:

public search = () => {
            if (!this.searchManager) {
                var self = this;
                Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
                    self.searchManager = new Microsoft.Maps.Search.SearchManager(self.map); // PROBLEM!!
  self.search(); 
                });

            } else {

            // remove any previous results from the map.
            this.map.entities.clear();

            // get the users query and geocode it.
            let query: string = (<HTMLInputElement>document.getElementById("txtInput")).value;
            this.geocodeQuery(query);
        }
5
  • If serchManager is really never set, you should find some error in the console. Like a network error or a thrown exception during module load. On the other hand, it is possible you just have to wait more, as the module loader function is asynchronous. Commented Nov 23, 2016 at 13:25
  • i've tried to call search() recursive when searchManager was not set, but that also didn't work via this.search(). Commented Nov 23, 2016 at 13:29
  • Just put a breakpoint in there and see if it runs this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map) ; Commented Nov 23, 2016 at 13:38
  • it gets hit but it doesn't seem to set the searchManager variable from the root of my class, so when I call the geocode function later on, the searchManager is undefined. Commented Nov 23, 2016 at 13:42
  • To avoid the problem that you ran into, you should consider using the noImplicitThis flag, which will help flag places where you may be losing a reference to this. Commented Nov 23, 2016 at 15:08

1 Answer 1

1

problem is that this variable doesn't refer to BMGeocode as you would expect but to the closure in which you are trying to use it. Try this instead:

var self = this
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
    self.searchManager = new Microsoft.Maps.Search.SearchManager(self.map) ; // PROBLEM: searchManager is never set?
});
Sign up to request clarification or add additional context in comments.

4 Comments

It's not the case with arrow functions.
"search" is arrow function, but there is closure inside loadModule that isn't
@juFo Definitely should work. The error is still the same?
@juFo is the object actually being created? try assigning it to temporary variable first and check if that isnt null

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.