BingMap - getting prototype of null error

I have searched google and stackoverflow, but could not find a solution for this issue. I am loading the map like this, in my view.

<img
      ng-src='https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/
              {{Latitude.__text}},{{Longitude.__text}}/12?mapSize=77,120&amp;
                           key={{Key}}'></img>

Below is how its loaded in index.html

<script type='text/javascript' src='https://www.bing.com/mapspreview/sdkrelease/mapcontrol?callback=loadMapScenario' async defer></script>
<script type='text/javascript' src='app/services/bing.js?' async defer></script>

Below is my controller code, where i am trying to call the maps.

function GetMap() {
    if (typeof Microsoft !== undefined && typeof Microsoft.Maps !== undefined &&
        Microsoft.Maps.Map !== null) {
        //Map API available add your map load code.
        angular.element(document).ready(function() {
            map = new Microsoft.Maps.Map(document.getElementById('myMapL'), {
                credentials: Key,
                mapTypeId: "r",
                zoom: 4
            });
        });
    } else {
        setTimeout(GetMap(), 100);
    }
}

I am getting the below error:

TypeError: Cannot read property 'prototype' of null
    at k (bing.js:11)
    at h (bing.js:11)
    at e (bing.js:11)
    at t.l [as instance] (bing.js:11)
    at h (bing.js:11)
    at e (bing.js:11)
    at t.l [as instance] (bing.js:11)
    at new Microsoft.Maps.Map (bing.js:13)
    at HTMLDocument.<anonymous> (file-location.js:121)
    at j (jquery-1.11.0.min.js:2)

Answers:

Answer

In the map script URL you are using a different callback function that you o function to load the map. (loadScenario vs GetMap). Also, it looks like you are using the redirect URL rather than the documented map script URL (this will likely break in the future). Try changing the map script URL to this:

<script type='text/javascript' src='http://www.bing.com/api/maps/mapcontrol?branch=experimental&callback=GetMap' async defer></script>

Not sure what bing.js is in your app. Assuming this is where you have you map load code. You will want to load this before the map script otherwise the map script may load before your code does and thus try to load the map before your GetMap function is loaded into the page.

Alternatively, you may find this code sample useful: https://github.com/Microsoft/BingMapsV8CodeSamples/blob/master/Samples/Experimental/Map_WithAngular1.html

Answer

It seems you are generating a static map only in your view, in that case the loading of Bing Maps API (http://www.bing.com/api/maps/mapcontrol) and initializing map control (GetMap function) could be omitted.

The reason why you are getting the error:

TypeError: Cannot read property 'prototype' of null

is most likely due to missing map container declaration in your view

<div id="myMapL"></div>

Example

var app = angular.module("myApp", []);
app.controller("bingMapsCtrl", function ($scope) {
 
    $scope.Key = "As1l7HRtrpkXzjXozp3M2ufUTDvj16b2MHlpscQmHJEtxYFZWqwyccSx7I5XXEW_";

});
 <script type='text/javascript' src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<div ng-app="myApp" ng-controller="bingMapsCtrl" ng-cloak>
        <!--div id="myMapL"></div-->
        <img
      ng-src='http://dev.virtualearth.net/REST/V1/Imagery/Map/Road/Bellevue%20Washington?mapLayer=TrafficFlow&amp;key={{Key}}'></img>
    </div>

Answer

Seems BING MAP API 8 has some issues with reference order, will try to report to Rick.

Does not Work:

<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script type='text/javascript' src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>

This fails on:

mapcontrol:11 Uncaught TypeError: Cannot read property 'prototype' of null
    at k (mapcontrol:11)
    at n.h [as create] (mapcontrol:11)
    at e (mapcontrol:11)
    at t.l [as instance] (mapcontrol:11)
    at n.h [as create] (mapcontrol:11)
    at e (mapcontrol:11)
    at t.l [as instance] (mapcontrol:11)
    at new Microsoft.Maps.Map (mapcontrol:13)
    at ChildScope.$scope.init (maptest.html:92)
    at HTMLDocument.<anonymous> (maptest.html:99)

Does Work:

<script type='text/javascript' src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>

But... that breaks epoch and is not how Angular is to be loaded. So back to the drawingboard.

Answer

Issue solved for me after wrapping the "loadMap" method with a "setTimeout":

HTML

<div class="bing-map-container">
  <div id='printoutPanel'></div>
  <div #bingMap id="myMap" style='width: 100vw; height: 100vh;'></div>
</div>

Component

import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {BingMapService} from './bing-map.service';
import {Subscription} from "rxjs";

@Component({
  moduleId: module.id,
  selector: 'bing-map',
  styleUrls: ['./bing-map.component.css'],
  templateUrl: './bing-map.component.html'
})
export class BingMapComponent implements OnInit, OnDestroy {
  @ViewChild('bingMap') bingMap: any;
  serviceSubject: Subscription;

  constructor(
    private bingMapService: BingMapService
  ) {}

  loadMap() {
    const map = new Microsoft.Maps.Map(this.bingMap.nativeElement, {});
  }

  ngOnInit() {
    this.serviceSubject = this.bingMapService.injectionSubject().subscribe((loaded) => {
      if (loaded) {
        window.setTimeout(() => {
          this.loadMap();
        });
      }
    });

    this.bingMapService.injectBingMapMainScript();
  }

  ngOnDestroy() {
    if (this.serviceSubject) {
      this.serviceSubject.unsubscribe();
    }
  }
}

Service

import {Observable, Subject} from 'rxjs';
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';

@Injectable({
  providedIn: 'root'
})
export class BingMapService {
  private subject = new Subject<any>();

  constructor(
    private http: Http,
  ) {}

  injectBingMapMainScript() {
    let script = document.createElement('script');
    script.src = 'https://www.bing.com/api/maps/mapcontrol?key=[YourKey]';
    script.async = true;

    document.body.appendChild(script);

    script.onload = () => {
      this.subject.next(true);
    };
  }

  injectionSubject(): Observable<any> {
    return this.subject.asObservable();
  }
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.