Launch Google Maps On Blazor - google-maps-api-3

I am trying to launch Google maps on my Server side Blazor app using JSInterop. I seem to have tried just about everything but can't get the map to show. Unfortunately there is very little samples if any about it on the internet since it's a fairly new framework and I am equally just getting my feet wet on Blazor myself, so I am probably doing a whole lot of things wrong. Any nudge in the right direction would be appreciated.
In my component file, I have:
#page "/MapTest"
#inject IJSRuntime JSRuntime
<style>
#map {
width: 60%;
height: 60%;
}
</style>
<h1>Display Google Map</h1>
<div #ref="map" id="map"></div>
#code {
ElementReference map; // reference to the DIV
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("Showgooglemap", null);
//StateHasChanged();
}
}
On my _Host.cshtml file, I have:
<script src="_framework/blazor.server.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=xxxmykeyxxx&v=3"></script>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(40.716948, -74.003563);
var options = {
zoom: 14, center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById
("map"), options);
}
//google.maps.event.addDomListener(window, 'load', initialize);
//i tried wrapping the call in a function to see if it helps
function Showgooglemap() {
google.maps.event.addDomListener(window, 'load', initialize);
}
</script>

Welcome #flylily, you are almost done. I run your code in my sample Blazor-server-side project. I only change two things. One is change height from percentage to pixel (for percentage height HTML 5) and another is invoke initialize function insteed of Showgooglemap becasuse initialize function already initialize your map on page load or first render. The complete codes are in following, try with these...
_Host.cshtml file,
<script src="_framework/blazor.server.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key={{put-your-api-key}}&v=3"></script>
<script>
function initialize() {
var latlng = new google.maps.LatLng(40.716948, -74.003563);
var options = {
zoom: 14, center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById
("map"), options);
}
</script>
MapTest.razor component,
#page "/MapTest"
#inject IJSRuntime JSRuntime
<h1>Display Google Map</h1>
<div id="map" style="height:500px;width:100%;">
</div>
#code{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("initialize", null);
StateHasChanged();
}
}
}
Finally, run your application & enjoy.

You can use the package BlazorGoogleMaps from rungwiroon as well. It supports
Map
Marker
Symbols
InfoWindow
Polygon, LineString, Rectangle, Circle
Routes
Coordinates
Bounds
Styles
and is available on Github and NuGet.
I'm using it and it works really well.

You can use this Nuget package. It will give your Blazor app full control over Google Static and JavaScript Maps API as well.
Usage can be complicated so recommend to read the documentation for more details and check the demo app.
Other Nuget package can help you access Browsers Geolocation services as well. See Geo JS docs as well as demo app.

Related

Rendering a Google Map without react-google-map

Has anyone been able to render a google map using React and not using the react-google-map plugin? I'm trying something like this:
var MapTab = React.createClass({
render: function() {
return <div className="map-container">
<div id='map' ></div>
</div>
},
componentDidMount: function(){
console.log("Hello")
window.onload = function(){
(function initMap() {
var markers = [];
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 37.7749300, lng: -122.4194200}
});
})();
}
}// end of cdm;
});
module.exports = MapTab;
Nothing I have tried has worked. I have tried capturing the map using refs as well but that did not render the map either. I have placed the google maps script in the header as well (with key) and have verified that the key is valid in a vanilla js project.
With componentDidMount you know you map container div has loaded, but you are not guaranteed that the external maps api has loaded yet. Google provides you the option to give a callback function (initMap() in their examples).
https://maps.googleapis.com/maps/api/js?key=&callback=initMap
Now you can proceed as follows, After your map component did mount you can:
window.initMap = this.initMap to make initMap from react available for Google maps to callback to.
load the google maps JS with initMap parameter.
In this.initMap in your component you can do your map stuff, because now you know your container ánd Google API have loaded.
const React = require('react')
const PropTypes = require('prop-types')
import Reflux from 'reflux'
const Radium = require('radium')
class Map extends Reflux.Component {
constructor(props) {
super(props)
this.loadJS = this.loadJS.bind(this)
this.initMap = this.initMap.bind(this)
}
componentDidMount() {
window.initMap = this.initMap;
if (typeof google === 'object' && typeof google.maps === 'object') {
this.initMap()
} else {
this.loadJS('https://maps.googleapis.com/maps/api/js?key=<API_KEY>&callback=initMap')
}
}
// https://github.com/filamentgroup/loadJS/blob/master/loadJS.js
loadJS(src) {
var ref = window.document.getElementsByTagName("script")[0];
var script = window.document.createElement("script");
script.src = src;
script.async = true;
ref.parentNode.insertBefore(script, ref);
}
initMap() {
var map = new google.maps.Map(this.refs.map, {
center: {lat: -34.397, lng: 150.644},
zoom: 8
})
}
render() {
return (<div ref='map'></div>)
}
}
module.exports = Radium(Map)
get rid of window.onload. By the time componentDidMount method is called window is already loaded so your initMap() function never fires.
It seems that you are not familiar with React Component Life Cycle yet.
https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle
or this: http://busypeoples.github.io/post/react-component-lifecycle/ (this has the table of order in which react's methods are executed)
Actually, in the componentDidMount() ("DID-mount" means the element has already been there on the page, so you can start binding events to it)
React Component's idea is interesting, so we don't need to use javascript's "window.onload()" or jQuery's "$(document).ready()"
Therefore, your code can be revised as follows:
render: function() {
return <div className="map-container">
<div id='map' ></div>
</div>
},
componentDidMount: function(){
console.log("Hello")
var markers = [];
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 37.7749300, lng: -122.4194200}
});
}// end of cdm;
PS: Besides, in order to make the map appear, you need to style the map-container and map correctly (which need a height in pixel, in your case of "0 px width, maybe you need to put the width, too - either in px or 100%) Feel free to style them, though!
You can render a google map easily using React Refs Which are an ideal solution when integrating with third party libraries. Like this:
class App extends React.Component {
constructor(props){
super(props)
this.state = {
// no state for now..
}
// Use createRef() to create a reference to the DOM node we want
this.myMapContainer = React.createRef()
}
componentDidMount() {
// Instead of using: document.getElementById, use the ref we created earlier to access the element
let map = new google.maps.Map(this.myMapContainer.current, {
center: { lat: -34.9973268, lng: -58.582614 },
scrollwheel: false,
zoom: 4
})
}
render() {
return (
<div className="container">
<div ref={this.myMapContainer} id="map"></div>
<div id="text"><p>Google Maps now requires the use of a valid API Key.
That's why you see the popup window "This page can't load Google Maps correctly."</p>
Go get one!
</div>
</div>
)
}
}
Working Example here
Note: Don't forget to place the <script> that makes the call to the Google Maps API. If you created your project using create-react-app, you can place the script inside of public/index.html

Using google places api with google geocode api together

I am using google places autocomplete api and now I want to get the geocode of that address and display that area on map.This is my code...
<head>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places"></script>
<script>
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
function initialize() {
var input = document.getElementById('searchTextField');
var autocomplete = new google.maps.places.Autocomplete(input);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<input id="searchTextField" type="text" size="50">
</body>
I know there is google geocde api but I really dont know how to do that.
I m doing all this in wordpress. Anybody has idea about this???
Looks like that's what you need:
<style>
#map-canvas {
width: 500px;
height: 500px;
}
</style>
Then, the JS
function initialize() {
// initial zoom and position
var myOptions = {
zoom: 14,
center: new google.maps.LatLng(-25.3, 133.8)
};
// create Map instance
var map = new google.maps.Map(document.getElementById('map-canvas'), myOptions);
// get input reference
var input = document.getElementById('searchTextField');
// create instance of autocomplete
var autocomplete = new google.maps.places.Autocomplete(input);
// listen for changes
google.maps.event.addListener(autocomplete, 'place_changed', function() {
// get the selected place
var place = this.getPlace();
// if there's a geometry available
if (place.geometry) {
// move the map to the position
map.panTo(place.geometry.location);
// update the zoom
map.setZoom(15);
// log the position
console.log(place.geometry.location.lat(),place.geometry.location.lng() )
}
})
}
More info: https://developers.google.com/maps/documentation/javascript/places-autocomplete

Google maps API v3: Can not call method 'lat' of null

I am using Google maps API v3, and this is my HTML file (mylocation.html) :
<!DOCTYPE html>
<html>
<head>
<title>Mylocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>
<script>
var map;
function initialize() {
var mapOptions = {zoom: 6};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions)n);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Location found using HTML5.'
});
map.setCenter(pos);
}, function () {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
When I open it on the Google Chrome, it works fine, and shows me my location.
In my project, I using WebVew to show this HTML file on Android. But when I run it, in LogCat, I get the following error:
"Uncaught TypeError: Cannot call method 'lat' of null at file:///mnt/sdcard/myloction.html:12"
(I have saved mylocation.html in the SDCard).
I'm not sure how to fix this? Could someone guide me with this?
To access Geolocation in the WebView, you need to do a bit of setup first.
You first must enable the feature in WebSettings: http://developer.android.com/reference/android/webkit/WebSettings.html#setGeolocationEnabled(boolean)
And you must also implement the WebChromeClient.onGeolocationPermissionsShowPrompt:
http://developer.android.com/reference/android/webkit/WebChromeClient.html#onGeolocationPermissionsShowPrompt(java.lang.String, android.webkit.GeolocationPermissions.Callback)
And please also ensure that your application has the appropriate Android permissions to access location.

youtube iframe api loadVideoById() error

I am adding youtube video to a companies website and would like them to display on non-flash devices. I have been playing with the youtube iframe API and updated one of their examples to allow a user to click on a link to change the video in the iframe. The edited code is:
<!DOCTYPE HTML>
<html>
<body>
<div id="player"></div>
<script>
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var done = false;
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'JW5meKfy3fY',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(evt) {
evt.target.playVideo();
}
function onPlayerStateChange(evt) {
if (evt.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
function loadVideo(videoID) {
if(player) { player.loadVideoById(videoID); }
}
</script>
Click me to change video
</body>
</html>
The only thing I added was:
function loadVideo(videoID) {
if(player) { player.loadVideoById(videoID); }
}
This works fine in Safari, Chrome and Firefox but does not work in IE7, 8 or 9. In IE7 and 8 it returns an error "Object does not support this property or method".
Is this an issue with the API or am I doing something wrong?
I had a similar problem, and it turned out that you shouldn't call any of the methods on the YT.Player object (including loadVideoById) as long as onPlayerReady hasn't been called.
Doing a check if(player) {...} isn't sufficient, the Player object will be created and some properties will already be available in out without the methods you need being available.
You will need to call the load video function from the onPlayerReady event.
For example, if you want to load a video when clicking a thumbnail do this (this would require jquery but it should get the point across):
function onPlayerReady(evt) {
evt.target.playVideo();
//declare the click even function you want
$('#thumbs a).click(function(){
//get a data-video-id attr from the <a data-video-id="XXXXXX">
var myvideo = $(this).attr('data-video-id');
//call your custom function
loadVideo(myvideo);
//prevent click propagation
return false;
});
}
This way you can be sure the player is loaded.
Preventing click propagation with return false after the call to player.loadVideoById in my click event handler did the trick for me.

Google Map V3 API Not working in localhost

I copied following javascript code from google maps documentation, but it doesn't work, it only shows a white blank page, nothing loads.
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Map Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<!--
Include the maps javascript with sensor=true because this code is using a
sensor (a GPS locator) to determine the user's location.
See: http://code.google.com/apis/maps/documentation/javascript/basics.html#SpecifyingSensor
-->
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?sensor=true"></script>
<script type="text/javascript">
var map;
function initialize() {
var myOptions = {
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
myOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Location found using HTML5.'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>
Since v3 require api key what's wrong with it? I checked in google chrome and firefox but no clue.
Looks like you are missing a closing html tag, unless that is a typo.
Add this </html> at the bottom of the page.
You need to provide a center location to create your map. In your initialize() function change the map options to include the location you want to start with:
var myCenter = new google.maps.LatLng(60.0,105.0);
var myOptions = {
zoom: 6,
center: myCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
When (or if) you get a location from the geolocation service the center will be changed by your code.
Old question, will answer anyhow in case anyone else lands here.
I ended up using a slightly different implementation to get this to work:
<script type="text/javascript">
function initialize() {
var mapOptions = {zoom: 8, center: new google.maps.LatLng(-34.397, 150.644)};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
}
function loadScript() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp'+
'&key={{API_KEY}}&sensor=false&callback=initialize';
document.body.appendChild(script);
}
window.onload = loadScript();
</script>
The part that I had to add to get it to work from other (nearly identical) versions of this, was the () at the end of loadScript(). The implicit function call simply was not happening.
You will need to replace {{API_KEY}} with your own. I am not sure if this is required, but it was part of what led me to a working implementation.
If you do not have one, follow the steps listed here

Resources