Google maps in blazor 3 stops the connection to my component - google-maps

I'm trying to build small app - allowing me to take 1-6 pictures and get my coordinates.
But after implementing google maps, the other functions in my app are breaking.
My google searches points me towards the google map I get through jQuery modifies the doom and makes the Blazor app drop the connection.
Im running Blazor 3, ServerPrerendered mode
I have spend 3 days googling on this issue now, and everything I tried have failed.
In short, when I render a google map, the other functions (like adding a picture to a model) crashes the app - so I can't click anything.
<div class="col-12 new-lead">
<EditForm Model="leadModel" OnValidSubmit=#ValidFormSubmitted>
<label for="imageInput">Take a picture</label>
#if (imageDictionary.Count > 0)
{
#foreach (var imageDataUrl in imageDictionary)
{
<div class="image-list__item" #onclick="(() => OnInputFileDelete(imageDataUrl.Key))">
<img src="#imageDataUrl.Key" />
Click to delete
</div>
}
}
<InputFile OnChange="OnInputFileChange" accept="image/png,image/gif,image/jpeg" id="imageInput" class="hidden"></InputFile>
<span>#leadModel.Latitude,#leadModel.Longitude</span>
<div id="map"></div>
<InputText id="Latitude" #bind-Value="leadModel.Latitude" class="hidden"/>
<InputText id="Longitude" #bind-Value="leadModel.Longitude" class="hidden"/>
<input type="submit" class="btn btn__big btn__big--white " value="Create" />
</EditForm>
</div>
In my On Initialized I get the the coordionates which is set in a session, once the user logs in.
The probme is that my OnAfterRender and OnInputFileChange conflicts at :
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await jsRuntime.InvokeVoidAsync("createMap", null);
}
}
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
var maxAllowedFiles = 6;
var format = "image/png";
foreach (var imageFile in e.GetMultipleFiles(maxAllowedFiles))
{
var resizedImageFile = await imageFile.RequestImageFileAsync(format, 200, 200);
var buffer = new byte[resizedImageFile.Size];
await resizedImageFile.OpenReadStream().ReadAsync(buffer);
var imageDataUrl = $"data:{format};base64,{Convert.ToBase64String(buffer)}";
imageDictionary.Add(imageDataUrl, buffer);
}
}
My Jquery map is a quite simple copy/paste
function createMap() {
navigator.geolocation.getCurrentPosition(function (position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy; console.log(latitude, longitude, accuracy);
var coords = new google.maps.LatLng(latitude, longitude);
var mapOptions = {
zoom: 19,
center: coords,
mapTypeControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.SMALL
},
mapTypeId: google.maps.MapTypeId.ROADMAP,
styles: [
{
featureType: "poi",
elementType: "labels",
stylers: [{ visibility: "off" }]
}
]
};
map = new google.maps.Map(
document.getElementById("map"), mapOptions
);
marker = new google.maps.Marker({
position: new google.maps.LatLng(position.coords.latitude, position.coords.longitude),
icon: {
url: "/content/images/pegman.png",
scaledSize: new google.maps.Size(20, 45)
// https://sites.google.com/site/gmapsdevelopment/
},
map: map,
label: {
color: 'transparent', // <= HERE
fontSize: '11px',
fontWeight: '900',
text: 'Example Label'
}
});
});
}
Everything loads in fine, the UI and the map.
But when I try to add a new picture I get the errors :
[2021-02-17T01:06:14.210Z] Information: Normalizing '_blazor' to 'https://localhost:44305/_blazor'.
blazor.server.js:1 [2021-02-17T01:06:14.458Z] Information: WebSocket connected to wss://localhost:44305/_blazor?id=ZK1ovXOGgNBBMwPZ1n3jVg.
[2021-02-17T01:06:17.282Z] Error: There was an error applying batch 4.
Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
[2021-02-17T01:06:17.307Z] Error: System.AggregateException: One or more errors occurred.
(TypeError:Cannot read property 'removeChild' of null) ---> System.InvalidOperationException:
TypeError: Cannot read property 'removeChild' of null at Microsoft.AspNetCore.Components.RenderTree.Renderer.InvokeRenderCompletedCallsAfterUpdateDisplayTask(Task updateDisplayTask, Int32[] updatedComponents)
[2021-02-17T01:06:17.308Z] Information: Connection disconnected.
Uncaught (in promise) Error: Cannot send data if the connection is not in the 'Connected' State.

solution was to add all map logic to a separate blazor component and load it into the view. That way the sockets won't break.

Related

how do I filter pins on Google Map pulled from a json api endpoint using Vue

I have a map with a number of pins on it, the pins are generated from an endpoint api (json). I want to filter the pins via an input that has a v-modal - the search criteria is already set up and is pulled from the same api.
Even if someone can give some tips as to where in the vue lifecycle the filter should happen, i.e mounted, updated computed ect
Originally I used this article as a reference
https://medium.com/#limichelle21/integrating-google-maps-api-for-multiple-locations-a4329517977a
created() {
axios
.get(
`https://cors-anywhere.herokuapp.com/myEndpoint`
)
.then(response => {
// JSON responses are automatically parsed.
this.allProperties = response.data;
this.markers = this.allProperties.map(function (x) {
return {
lat: parseFloat(x.lat).toFixed(3),
lng: parseFloat(x.lng).toFixed(3),
add: x.dispAddress,
propId: x.property_id,
propPrice: x.outputAskingPrice,
propImg: x.imagePath
};
});
this.allProperties = response.data.map(x => {
x.searchIndex = `${x.sellingStatus} ${x.priceType} ${x.typeNames[0]} ${x.typeNames[1]} ${x.dispAddress}`.toLowerCase();
return x;
});
});
},
mounted: function () {
var _this = this;
function initMap() {
var center = {
lat: 53,
lng: -3
};
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 10,
center: center
});
var newPin = new google.maps.Marker({
position: center,
map: map
});
}
},
updated() {
var _this = this;
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 9,
center: new window.google.maps.LatLng(55.961, -3)
});
var infowindow = new google.maps.InfoWindow({});
var newPin;
var count;
for (count = 0; count < _this.markers.length; count++) {
newPin = new google.maps.Marker({
position: new google.maps.LatLng(
_this.markers[count].lat,
_this.markers[count].lng
),
map: map,
icon: "../assets/img/map-pin.png"
});
google.maps.event.addListener(
newPin,
"click",
(function (newPin, count) {
return function () {
infowindow.setContent(` ${_this.markers[count].add} <p> ${_this.markers[count].propPrice}</p><img src="${_this.markers[count].propImg}"><p>`);
infowindow.open(map, newPin);
};
})(newPin, count)
);
}
If you have v-model on an <input> field like mentioned in your question, you are binding the value of this <input> field to a variable probably defined in the data part of your Vue component. The value is always up to date in the model (reactive binding). You can watch this value and then trigger a function which updates Google Maps. Here is an example:
Vue.component('demo', {
data () {
return {
inputField: ''
};
},
created () {
console.log('Component script loaded, HTML not yet ready, load the data from your backend. Use a flag like isLoading or similar to indicate when the data is ready to enable input.');
},
mounted () {
console.log('Component mounted, HTML rendered, load Google Maps');
},
watch: {
inputField (newValue) {
console.log(`inputField changed to ${newValue}. Trigger here a method which update Google Maps. Make sure to debounce the input here, so that it does not trigger a Google Maps update too often.`);
}
},
template: `
<div>
<input type="text" v-model="inputField" placeholder="Lookup place">
</div>`
});
new Vue({ el: '#vue-demo-container' });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vue-demo-container">
<demo></demo>
</div>

Cross-Origin Rejection Rejected: Same Origin policy prohibits the reading of remote resources (Reason: CORS request was not successful)

good night Sir,
i want to show google map from getJson Url, and i already have method to parse data in database to jsonArray on the same project (other controller), when i call the url in map, i got this error
Cross-Origin Rejection Rejected: Same Origin policy prohibits the reading of remote resources at http://127.0.0.1:8080/edclistapps/map_list. (Reason: CORS request was not successful)
and i have js with getJSON method to call (json) from another service in my project to show marker in google map, and that service can be work, but my js and my getJson have console error, this is my js
<div class="controls">
<select id="type" onchange="filterMarkers(this.value);">
<option value="">Merchant Grub</option>
<option value="BAKMI GM">BAKMI GM</option>
<option value="CHATIME">CHATIME</option>
<option value="PUYO">PUYO</option>
</select>
</div>
<div id="map-canvas"></div>
<script>
var gmarkers1 = [];
var markers1 = [];
var infowindow = new google.maps.InfoWindow({
content: ''
});
// init map
function initialize() {
var center = new google.maps.LatLng(-6.121435, 106.774124);
var styles = [{ "stylers": [{ "saturation": -80 }, { "gamma": 2 }] }, { "featureType": "water", "stylers": [{ "lightness": -15 }] }];
var styledMap = new google.maps.StyledMapType(styles, { name: "EDC" });
var mapOptions = { scrollwheel: false, zoom: 4, center: center, mapTypeControlOptions: { mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style'] } };
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
map.mapTypes.set('map_style', styledMap);
map.setMapTypeId('map_style');
var url = "http://127.0.0.1:8080/edclistapps/map_list";
$.getJSON(url, function (markers1) {
$.each(markers1, function(key,val){
addMarker(key)
});
});
}
// add markers to map
function addMarker(marker) {
var category = marker[4];
var title = marker[3];
var pos = new google.maps.LatLng(marker[8], marker[9]);
var content = marker[3];
var city = marker[6];
var myIcon='http://ruralshores.com/assets/marker-icon.png';
marker1 = new google.maps.Marker({
title: title,
position: pos,
category: category,
map: map,
icon: myIcon
});
gmarkers1.push(marker1);
// marker click listener
google.maps.event.addListener(marker1, 'click', (function (marker1, content) {
return function () {
console.log('Gmarker 1 gets pushed');
infowindow.setContent(content);
// infowindow.setContent(city);
infowindow.open(map, marker1);
// map.panTo(this.getPosition()); // pan to lat/long of map marker
map.setZoom(12);
}
})(marker1, content));
}
// filter markers by category
filterMarkers = function (category) {
for (i = 0; i < markers1.length; i++) {
marker = gmarkers1[i];
// If is same category or category not picked
if (marker.category == category || category.length === 0) {
marker.setVisible(true);
}
// categories don't match
else {
marker.setVisible(false);
}
}
}
// Init map
initialize();
</script>
i'm using springboot and thymeleaf, what must i do to make my code work?

How do I do bind to property title of a marker from google maps with vuejs?

I am working with api google maps now I am development with vuejs now exist the posibility from bind a property to the property title from markers, for example
this is my component on vuejs
Vue.component('root-map',{
template: `
<div id="sidebar_builder"
style="width: 100%; height: 600px;">
</div>
`,
data: function(){
return {
map:null,
marker:{
title: 'hello'
}
}
},
mounted: function () {
this.$nextTick(function () {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
};
this.map = new google.maps.Map(document.getElementById('sidebar_builder'),mapOptions);
var marker_icon= new google.maps.Marker({
position: myLatlng,
title: this.marker.title}); // the most important part
marker_icon.setMap(this.map);
});
}
});
Now when I want change the property markers.title='I change' and happend nothing, the markers on the maps keep 'hello', could you please how do I do it ? If can do it without use method native from api google maps thanks!!
you can use watch
watch: {
marker() {
this.reDrawMarkers()
}
}
more info vue watcher https://v2.vuejs.org/v2/guide/computed.html#Watchers
if you dont know how to redraw markers also you can look google documentation
https://developers.google.com/maps/documentation/javascript/examples/marker-remove

Google Map Api Marker not showing with Reactjs

I am trying to display a google map with a marker. I am using React.js. The map displays in the correct location, but the marker does not show and I get multiple 'object is not extensible' error in the browser console
The code looks like this
/** #jsx React.DOM */
var Map = React.createClass({
initialize: function() {
var lat = parseFloat(this.props.lat);
var lng = parseFloat(this.props.lon);
var myPosition = new google.maps.LatLng(lat,lng);
var mapOptions = {
center: myPosition,
zoom: 8
};
var map = new google.maps.Map(this.getDOMNode(), mapOptions);
var marker = new google.maps.Marker({position: myPosition, title: 'Hi', map: map});
},
componentDidMount: function(){
this.initialize();
},
render:function(){
return <div className="map"/>
}
});
detailed errors from console:
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Can't add property onerror, object is not extensible main.js:3
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Cannot read property 'style' of undefined VM3577:69
Uncaught TypeError: Can't add property onerror, object is not extensible
Craig Savolainen has a nice explanation on using Google Maps as a React Component here, the gist for the example is here. I acomplished the marker render with the following code:
var ExampleGoogleMap = React.createClass({
getDefaultProps: function () {
return {
initialZoom: 8,
mapCenterLat: 43.6425569,
mapCenterLng: -79.4073126,
};
},
componentDidMount: function (rootNode) {
var mapOptions = {
center: this.mapCenterLatLng(),
zoom: this.props.initialZoom
},
map = new google.maps.Map(document.getElementById('react-valuation-map'), mapOptions);
var marker = new google.maps.Marker({position: this.mapCenterLatLng(), title: 'Hi', map: map});
this.setState({map: map});
},
mapCenterLatLng: function () {
var props = this.props;
return new google.maps.LatLng(props.mapCenterLat, props.mapCenterLng);
},
render: function () {
return (
<div className='map-gic'></div>
);
}
});
Working jsFiddle

Sencha touch - unable to google map markers

I'm learning sencha touch and trying put markers on the google map. I've looked at most of the examples online but I'm unable to get the marker and the infoWindow to work. Below is my code:
myApp.views.MapCard = Ext.extend(Ext.Panel, {
id: "mapcard",
layout: 'card',
initComponent: function() {
this.map = new Ext.Map({
useCurrentLocation: true,
mapOptions: {
zoom: 12,
},
});
this.panel = new Ext.Panel({
layout: 'fit',
items: this.map,
});
this.items = this.panel;
myApp.views.MapCard.superclass.initComponent.call(this);
refresh = function(theMap) {
var geoTag = {
lat: '47.584863',
longi: '-122.147026',
text: 'Hello World',
}
addMarker(geoTag, theMap);
}
addMarker = function(geoTag, theMap) {
var latLng = new google.maps.LatLng(geoTag.lat, geoTag.longi);
var marker = new google.maps.Marker({
map: theMap.map,
position: latLng
});
google.maps.event.addListener(marker, "click", function() {
geoTagBubble.setContent(tweet.text);
geoTagBubble.open(theMap.map, marker);
});
};
geoTagBubble = new google.maps.InfoWindow();
refresh(this.map);
},
});
Ext.reg('mapcard', myApp.views.MapCard);
I'm also unable to get the current location of the user, I'm pretty sure that the map is not loaded during the initComponent. I would be calling a json service to pull the lat/lon and loop through later. If there is a better implementation, please let me know!
Thanks a ton!
Here's a pretty minimal example application that demonstrates this:
http://septa.mobi
You can find the source code under view-source or on GitHub:
https://github.com/mjumbewu/Septnuts/
Here's panel where marker are added to a map:
https://github.com/mjumbewu/Septnuts/blob/master/src/Septnuts/MapPanel.js
WARNING: there is a bug in Sencha Touch 1.x that prevents embedded Google Maps from receiving ANY click events
You need to include this patch after including sencha-touch.js in order for any click listener on the map to work:
https://github.com/mjumbewu/Septnuts/blob/master/src/sencha-maptouch-patch.js