PDA

View Full Version : [CLOSED] Google maps in Ext.Panel



Jurke
Jan 31, 2020, 9:03 AM
Hi
I would like an example of how to implement Google maps in a Ext.Panel.
I could not find that of the forum nor the Examples explorer, can you please provide such an example?

Regards
Mikael

fabricio.murta
Jan 31, 2020, 6:32 PM
Hello @Jurke!

While Ext.NET Mobile has specific bing map (https://github.com/extnet/mobile.ext.net/blob/master/src/StandaloneExamples/BingMap_Basic.aspx) and google maps (https://github.com/extnet/mobile.ext.net/blob/master/src/StandaloneExamples/Map_Basic.aspx) components (*), the classic version never implemented specific google maps components.

But this does not really mean much, just because you can easily embed google maps the way you need by using loaders to specify the embed url (https://examples5.ext.net/#/Panel/BodyMask/Custom_Mask/) in any component accepting it.

Panels, as well as windows, are such an example, and here's a sample code embedding a google map:



<%@ Page Language="C#" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<ext:ResourceManager runat="server" Theme="Crisp" />
<ext:Panel runat="server" Title="The Blue Mosque" Width="800" Height="600" Frame="true">
<Loader
runat="server"
Url="https://www.google.com/maps/embed/v1/view?zoom=10&center=41.0058077,28.9761733&key=api_key_here"
DisableCaching="false"
/>
</ext:Panel>
</div>
</form>
</body>
</html>


At the time of the writing of this answer, google offered a tool to help generate the embed URL that you should add; notice you need an API key from google to use it; Ext.NET has no relationship with google and to that point onwards is beyond our reach.
- Google - Quick Start Build a Map (https://developers.google.com/maps/documentation/embed/start)

Hope this helps!

*) see examples live from your mobile or desktop in mobile emulation mode here: https://mobile.ext.net/#menu/ui

Jurke
Feb 03, 2020, 11:31 AM
Hi!

Even though that implementation works, we need to have greater control of the maps object, and there for need to create it through JS.
This works, but it seems as the sizing of the div inside the Panel wont work properly.
If I set the width and height to a fixed value it shows the map correct, but with height and width set to 100% to match the parent Panel nothing is shown.
Any ideas on how to get the sizing properly set?


<%@ Page Language="C#" %>


<%@ Import Namespace="Ext.Net.Utilities" %>


<!DOCTYPE html>
<html>
<head runat="server">
<title>Map in Tab panel</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">


<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
}
</script>


<script src="https://maps.googleapis.com/maps/api/js?key=[KEY GOES HERE]&callback=initMap" async defer></script>




</head>
<body>
<form runat="server">
<ext:ResourceManager ID="ResourceManager2" runat="server" />


<ext:Viewport runat="server" Layout="Border">
<Items>
<ext:TabPanel
runat="server"
Region="Center"
Title="TabPanel"
MarginSpec="5 5 5 0">
<Items>
<ext:Panel runat="server" Title="Tab 1" Layout="Fit">
<Items>
<ext:Portal runat="server" Border="false">
<Items>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet1" runat="server" Title="Another Panel 1" Icon="Accept" Height="500">
<Content>
<ext:Panel
runat="server"
Height="500"
Border="false"
Region="North"
Cls="app-header"
BodyCls="app-header-content">
<Content>
<div style="width: 500px; height: 500px;" id="map"></div>
</Content>
</ext:Panel>
</Content>
</ext:Portlet>
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet2" runat="server" Title="Panel 2" />
<ext:Portlet ID="Portlet3" runat="server" Title="Another Panel 2" />
<ext:Button runat="server" Text="Button" OnClientClick="button();" />
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet4" runat="server" Title="Panel 3" />
<ext:Portlet ID="Portlet5" runat="server" Title="Another Panel 3" />
</Items>
</ext:PortalColumn>
</Items>
</ext:Portal>


</Items>
</ext:Panel>
</Items>
</ext:TabPanel>
</Items>
</ext:Viewport>


</form>


</body>
</html>




Best regards,
Mikael

fabricio.murta
Feb 03, 2020, 12:45 PM
Hello @Mikael!

First off just by looking at your example I can point you one thing:

Whenever you use an Ext.NET component within a block, if there are just Ext.NET components, avoid using the <Content> block to wrap it. Basically this helps layout, and making everything fit.

I'm referring to, specifically, line 52 of your code sample. You may (or rather, should) use <Items> there instead. This may help you get the panel to stick to the size you need. Besides, as you want just something to wrap around the google maps component, you may try first to just have the map div within that portlet and, in case it doesn't work for your needs, you can switch the panel to an ext:Container, which would be "lighter" to the page.

Further down a little, yes, where you want to have the div (immediately wrapping it) should be a <Content> tag as you used. Bear in mind it still means Ext.NET's layout system won't be touching whatever's inside it (and that's one of the reasons you have issues with height and width set to 100%).

That said, you won't get auto-fit like that out of the box, unfortunately. You'd have to wire width/height to resize or load events, depending how your page behaves. If the outer components changes dimensions as client side window is resized, or device orientation changes, then you probably want the former.

Going even further down again, couldn't we just discard any usage of <Content> blocks, letting Ext.NET fully handle layout for us? Wouldn't the following work for you?



<ext:Portlet ID="Portlet1" runat="server" Title="Another Panel 1" Icon="Accept" Height="500">
<Items>
<ext:Container runat="server" ID="map" />
</Items>
</ext:Portlet>


Notice I changed the block in your code corresponding to lines 51-65. The ext:Container, as being an <Items> element, fits to its surrounding PortLet (due to its default layout), then nothing else should be needed, as google maps will replace everything within the container element with its own, 100%-width-height, HTML elements.

Is that an acceptable approach? If not, we'd need to dig down the resize/reload event to give width/height to the inner div depending on its surrounding component's "html body space".

fabricio.murta
Feb 07, 2020, 9:20 PM
Hello @Mikael!

Did our answer here help you at all? I see you got a couple new threads and still no reply to our last post here. Do you still need help with this inquiry? Your feedback about the answer is greatly anticipated (just if it helped or not)!

Jurke
Feb 10, 2020, 8:33 AM
Hi
Sorry for that!
I could not get your solution with the <ext:container.. > to work, I had to use a div with position absolute. Then the map shows and fills the panel. The problem now is that the when the I resize the panel, the map will not resize. I posted my solution below.

Regards
Mikael



<%@ Page Language="C#" %>


<%@ Import Namespace="Ext.Net.Utilities" %>


<!DOCTYPE html>
<html>
<head runat="server">
<title>Map in Tab panel</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">


<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
}
</script>


<script src="https://maps.googleapis.com/maps/api/js?key=XXX&callback=initMap" async defer></script>




</head>
<body>
<form runat="server">
<ext:ResourceManager ID="ResourceManager2" runat="server" />


<ext:Viewport runat="server" Layout="Border">
<Items>
<ext:TabPanel
runat="server"
Region="Center"
Title="TabPanel"
MarginSpec="5 5 5 0">
<Items>
<ext:Panel runat="server" Title="Tab 1" Layout="Fit">
<Items>
<ext:Portal runat="server" Border="false">
<Items>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet1" runat="server" Title="Another Panel 1" Icon="Accept" Height="500">
<Content>
<ext:Panel
runat="server"
Height="500"
Border="false"
Region="North"
Cls="app-header"
BodyCls="app-header-content">
<Content>
<div style="width: 100%; height: 100%; position: absolute;" id="map"></div>
</Content>
</ext:Panel>
</Content>
</ext:Portlet>
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet2" runat="server" Title="Panel 2" />
<ext:Portlet ID="Portlet3" runat="server" Title="Another Panel 2" />
<ext:Button runat="server" Text="Button" OnClientClick="button();" />
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet4" runat="server" Title="Panel 3" />
<ext:Portlet ID="Portlet5" runat="server" Title="Another Panel 3" />
</Items>
</ext:PortalColumn>
</Items>
</ext:Portal>


</Items>
</ext:Panel>
</Items>
</ext:TabPanel>
</Items>
</ext:Viewport>


</form>


</body>
</html>

fabricio.murta
Feb 10, 2020, 8:57 PM
Hello @Mikael!

Maybe the position to place the component was not clear enough in my tests, or maybe you have something else affecting it.

Here's the resulting code of the page in the approach I suggested:



<%@ Page Language="C#" %>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Map in Tab panel</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<script>
var map;
function initMap() {
Ext.onReady(function () {
map = new google.maps.Map(document.getElementById('map'), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=XXX&callback=initMap"></script>
</head>
<body>
<form runat="server">
<ext:ResourceManager ID="ResourceManager2" runat="server" />
<ext:Viewport runat="server" Layout="Border">
<Items>
<ext:TabPanel
runat="server"
Region="Center"
Title="TabPanel"
MarginSpec="5 5 5 0">
<Items>
<ext:Panel runat="server" Title="Tab 1" Layout="Fit">
<Items>
<ext:Portal runat="server" Border="false">
<Items>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet1" runat="server" Title="Another Panel 1" Icon="Accept" Height="500">
<Items>
<ext:Container runat="server" ID="map" />
</Items>
</ext:Portlet>
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet2" runat="server" Title="Panel 2" />
<ext:Portlet ID="Portlet3" runat="server" Title="Another Panel 2" />
<ext:Button runat="server" Text="Button" OnClientClick="button();" />
</Items>
</ext:PortalColumn>
<ext:PortalColumn runat="server">
<Items>
<ext:Portlet ID="Portlet4" runat="server" Title="Panel 3" />
<ext:Portlet ID="Portlet5" runat="server" Title="Another Panel 3" />
</Items>
</ext:PortalColumn>
</Items>
</ext:Portal>
</Items>
</ext:Panel>
</Items>
</ext:TabPanel>
</Items>
</ext:Viewport>
</form>
</body>
</html>


Notice lines 39-43 envelop the portlet the maps component should be. In my side, it fits and follows resizing nicely, I see no issues.

Earlier, between lines 9-19, I modified your script as it was being called too early in Firefox only (chrome and edge called it when the resources were available so the google script's defer keyword helped; not Firefox. In fact, with the change at least, the async defer bit in the line including google maps API code is useless and may be dropped.

Hope this helps!

Jurke
Feb 11, 2020, 9:38 AM
Thanks, that worked great!

You can close this thread now.

Regards
Mikael

fabricio.murta
Feb 11, 2020, 6:41 PM
Glad it helped, thanks for the feedback!