Closed cblanchard-aa closed 3 weeks ago
Neven create anything in OnInitializedAsync since map load asyn and could be created after this method. Use map OnInitializedAsync like here https://github.com/rungwiroon/BlazorGoogleMaps/blob/master/ServerSideDemo/Pages/MapAdvancedMarkerViewPage.razor#L48
Does it works now?
Neven create anything in OnInitializedAsync since map load asyn and could be created after this method. Use map OnInitializedAsync like here https://github.com/rungwiroon/BlazorGoogleMaps/blob/master/ServerSideDemo/Pages/MapAdvancedMarkerViewPage.razor#L48
Does it works now?
Funny, I've been banging my head against the wall this afternoon with this exact issue. I will double-check your suggestion first and report back.
I doublechecked, and to clarify some more points:
The proposed implementation works, until the page is refreshed. I did, however, pinpoint the cause of my issue. Using breakpoints that hide one map or the other, to show a different-sized map for mobile vs desktop causes the mentioned error.
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Map: Expected mapDiv of type HTMLElement but was passed null.
InvalidValueError
at _.yj (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:227:373)
at new Io (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:298:310)
at Object.createObject (http://localhost:25498/_content/BlazorGoogleMaps/js/objectManager.js:366:27)
at http://localhost:25498/_framework/blazor.webassembly.js:1:2878
at new Promise (<anonymous>)
at b.beginInvokeJSFromDotNet (http://localhost:25498/_framework/blazor.webassembly.js:1:2835)
at Object.vn [as invokeJSJson] (http://localhost:25498/_framework/blazor.webassembly.js:1:58849)
at http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:178364
at Tl (http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:179198)
at wasm://wasm/00b2193a:wasm-function[349]:0x1fab4
Microsoft.JSInterop.JSException: Map: Expected mapDiv of type HTMLElement but was passed null.
InvalidValueError
at _.yj (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:227:373)
at new Io (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:298:310)
at Object.createObject (http://localhost:25498/_content/BlazorGoogleMaps/js/objectManager.js:366:27)
at http://localhost:25498/_framework/blazor.webassembly.js:1:2878
at new Promise (<anonymous>)
at b.beginInvokeJSFromDotNet (http://localhost:25498/_framework/blazor.webassembly.js:1:2835)
at Object.vn [as invokeJSJson] (http://localhost:25498/_framework/blazor.webassembly.js:1:58849)
at http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:178364
at Tl (http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:179198)
at wasm://wasm/00b2193a:wasm-function[349]:0x1fab4
at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at GoogleMapsComponents.Helper.<MyInvokeAsync>d__10`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
at GoogleMapsComponents.JsObjectRef.CreateAsync(IJSRuntime jsRuntime, Guid guid, String functionName, Object[] args)
at GoogleMapsComponents.Maps.Map.CreateAsync(IJSRuntime jsRuntime, ElementReference mapDiv, MapOptions opts)
at GoogleMapsComponents.MapComponent.InitAsync(ElementReference element, MapOptions options)
at GoogleMapsComponents.GoogleMap.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
Reverting to a single map means the proposed solution works like a charm. Perhaps this could be handled better, as it can be confusing.
Do you have sample to reproduce?
Do you have sample to reproduce?
I am working on a reliable one and will report back soon.
Neven create anything in OnInitializedAsync since map load asyn and could be created after this method. Use map OnInitializedAsync like here https://github.com/rungwiroon/BlazorGoogleMaps/blob/master/ServerSideDemo/Pages/MapAdvancedMarkerViewPage.razor#L48
Does it works now?
I am loading data that is totally separate from the map, not doing anything with the map in this method.
@valentasm1 The above commit/fork is a 1:1 repro of the issue, with 100% accuracy.
The repro steps were added in a later commit:
BlazorGoogleMaps.sln
.ClientSideDemo
./mapEvents
.Note that the solution works perfectly fine when not involving the Mudblazor library, but I wanted to give you a proper repro, as I do think there is room for improvement here.
I doublechecked, and to clarify some more points:
The proposed implementation works, until the page is refreshed. I did, however, pinpoint the cause of my issue. Using breakpoints that hide one map or the other, to show a different-sized map for mobile vs desktop causes the mentioned error.
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Map: Expected mapDiv of type HTMLElement but was passed null. InvalidValueError at _.yj (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:227:373) at new Io (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:298:310) at Object.createObject (http://localhost:25498/_content/BlazorGoogleMaps/js/objectManager.js:366:27) at http://localhost:25498/_framework/blazor.webassembly.js:1:2878 at new Promise (<anonymous>) at b.beginInvokeJSFromDotNet (http://localhost:25498/_framework/blazor.webassembly.js:1:2835) at Object.vn [as invokeJSJson] (http://localhost:25498/_framework/blazor.webassembly.js:1:58849) at http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:178364 at Tl (http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:179198) at wasm://wasm/00b2193a:wasm-function[349]:0x1fab4 Microsoft.JSInterop.JSException: Map: Expected mapDiv of type HTMLElement but was passed null. InvalidValueError at _.yj (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:227:373) at new Io (https://maps.googleapis.com/maps/api/js?libraries=places&key=API_KEY_OBFUSCATED&v=weekly&callback=google.maps.__ib__:298:310) at Object.createObject (http://localhost:25498/_content/BlazorGoogleMaps/js/objectManager.js:366:27) at http://localhost:25498/_framework/blazor.webassembly.js:1:2878 at new Promise (<anonymous>) at b.beginInvokeJSFromDotNet (http://localhost:25498/_framework/blazor.webassembly.js:1:2835) at Object.vn [as invokeJSJson] (http://localhost:25498/_framework/blazor.webassembly.js:1:58849) at http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:178364 at Tl (http://localhost:25498/_framework/dotnet.runtime.8.0.6.xm0i2q3k8g.js:3:179198) at wasm://wasm/00b2193a:wasm-function[349]:0x1fab4 at Microsoft.JSInterop.JSRuntime.<InvokeAsync>d__16`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at GoogleMapsComponents.Helper.<MyInvokeAsync>d__10`1[[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext() at GoogleMapsComponents.JsObjectRef.CreateAsync(IJSRuntime jsRuntime, Guid guid, String functionName, Object[] args) at GoogleMapsComponents.Maps.Map.CreateAsync(IJSRuntime jsRuntime, ElementReference mapDiv, MapOptions opts) at GoogleMapsComponents.MapComponent.InitAsync(ElementReference element, MapOptions options) at GoogleMapsComponents.GoogleMap.OnAfterRenderAsync(Boolean firstRender) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
Reverting to a single map means the proposed solution works like a charm. Perhaps this could be handled better, as it can be confusing
I am not conditionally showing or hiding the map in this instance, it should be on the page in load. However, I am using BlazorBootstrap library, so there could be something else going on there as well.
I will test some things out when I get some time away from work to get more info and see If i can get a sample.
I am not conditionally showing or hiding the map in this instance, it should be on the page in load. However, I am using BlazorBootstrap library, so there could be something else going on there as well.
I will test some things out when I get some time away from work to get more info and see If i can get a sample.
For your sanity, I can confirm the proposed solution works fine in NET8, old-school WASM. Do note that the conditional hiding also is not relevant when done as follows:
@if (_myval)
{
<GoogleMap Height="400px" @ref="@_map1" Id="map1" Options="@_mapOptions" OnAfterInit="OnAfterInitAsync" />
}
else
{
<GoogleMap Height="400px" @ref="@_map1" Id="map1" Options="@_mapOptions" OnAfterInit="OnAfterInitAsync" />
}
The above code does not cause the issue.
Perhaps, like you are indicating, we are both doing something that triggers it. I did take the effort to repro my exact cause, as it might be of use to @valentasm1 to chase down the root cause here.
MudBlazor has some js listeners on resize. It trigger and remove element from DOM. While OnAfterRenderAsync in MapComponent is already trigered with passing ElementReference. When it reaches js ElementReference dont exist since it was removed from DOM by MudBlazor. All this come from my quick investigation. Need more info for confirmation. Some resources. https://github.com/MudBlazor/MudBlazor/issues/148#issuecomment-732156394 src/MudBlazor/TScripts/mudResizeListener.js src/MudBlazor/TScripts/mudResizeObserver.js
I think solution is one line somewhere in code. Just not sure where exactly :). Probably most stupid one is to add check in js, but i dont like it. It smells :). I will leave it to you since i am sure you have more knowledge about this
MudBlazor has some js listeners on resize. It trigger and remove element from DOM. While OnAfterRenderAsync in MapComponent is already trigered with passing ElementReference. When it reaches js ElementReference dont exist since it was removed from DOM by MudBlazor. All this come from my quick investigation. Need more info for confirmation. Some resources. MudBlazor/MudBlazor#148 (comment) src/MudBlazor/TScripts/mudResizeListener.js src/MudBlazor/TScripts/mudResizeObserver.js
I think solution is one line somewhere in code. Just not sure where exactly :). Probably most stupid one is to add check in js, but i dont like it. It smells :). I will leave it to you since i am sure you have more knowledge about this
This is correct, MudHidden
removes the element from the DOM. This might not suit for every component, like this component or another example is file upload. Responsive CSS should be used instead to hide the component.
Dirty workaround could be just ovverider js action window.blazorGoogleMaps.objectManager.createObject Or use blazorGoogleMapsBeforeStringify somehow https://github.com/rungwiroon/BlazorGoogleMaps/pull/312 I think there are more ways to solve it in js. Most of them hacky way. Since it is not related to this library then i am closing issue. If you have other suggestion please update. Maybe other will find it usefull.
I did kind of hijack @cblanchard-aa 's ticket. My bad :) Thanks for the response @ScarletKuro & @valentasm1, it is very much appreciated.
I did kind of hijack @cblanchard-aa 's ticket. My bad :) Thanks for the response @ScarletKuro & @valentasm1, it is very much appreciated.
I appreciate you hijacking it! I am busy trying to build an application for my company :). Appreciate the quick response time and turnaround. The issue is resolved on my end, you guys are awesome!
Edit - for context - workaround posted in my inital comment is the solution that I am rolling with :)
Error is thrown when calling Autocomplete.CreateAsync after an async task has been run in the pages OnInitializedAsync method.
Currently you can get around this issue by running your async tasks in the pages OnAfterRenderAsync method.
blazor.web.js:1 [2024-06-17T14:52:34.486Z] Error: Microsoft.JSInterop.JSException: Map: Expected mapDiv of type HTMLElement but was passed null. InvalidValueError at _.yj (https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY&v=weekly&callback=google.maps.__ib__:227:373) at new Io (https://maps.googleapis.com/maps/api/js?libraries=places&key=YOUR_API_KEY&v=weekly&callback=google.maps.__ib__:298:310) at Object.createObject (http://localhost:5204/_content/BlazorGoogleMaps/js/objectManager.js:366:27) at http://localhost:5204/_framework/blazor.web.js:1:3244 at new Promise ()
at y.beginInvokeJSFromDotNet (http://localhost:5204/_framework/blazor.web.js:1:3201)
at gn._invokeClientMethod (http://localhost:5204/_framework/blazor.web.js:1:62841)
at gn._processIncomingData (http://localhost:5204/_framework/blazor.web.js:1:60316)
at connection.onreceive (http://localhost:5204/_framework/blazor.web.js:1:53957)
at i.onmessage (http://localhost:5204/_framework/blazor.web.js:1:82102)
at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
at GoogleMapsComponents.Helper.MyInvokeAsync[TRes](IJSRuntime jsRuntime, String identifier, Object[] args)
at GoogleMapsComponents.JsObjectRef.CreateAsync(IJSRuntime jsRuntime, Guid guid, String functionName, Object[] args)
at GoogleMapsComponents.Maps.Map.CreateAsync(IJSRuntime jsRuntime, ElementReference mapDiv, MapOptions opts)
at GoogleMapsComponents.MapComponent.InitAsync(ElementReference element, MapOptions options)
at GoogleMapsComponents.GoogleMap.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)