SAPUI5 with Google Maps
Creating a simple SAPUI5 Application with Google Maps
1. Creation of an empty project
I have created an empty project with MS Matrix (you can use any environment you like instead).
Striked out files are generated automatically and actually not needed, if you work with another editor.
Default.cshtml file is a default handler for the site. Let’s start with it.
2. Default.cshtml
Default.cshtml has following content.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Maps</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<script id="sap-ui-bootstrap"
type="text/javascript"
src="https://sapui5.netweaver.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-language="en_US"
type="text/javascript"
data-sap-ui-libs="sap.m,sap.makit"
data-sap-ui-theme="sap_mvi"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_APP_KEY&sensor=false"
type ="text/javascript"></script>
<script type="text/javascript" src="j/app.js" ></script>
<style>
.myMap {
height: 100%;
width: 100%
}
</style>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
Here is an explanation of included parts.
First special part is including and initializing SAPUI5 library as described in developer guide.
<script id="sap-ui-bootstrap"
type="text/javascript"
src="https://sapui5.netweaver.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-language="en_US"
type="text/javascript"
data-sap-ui-libs="sap.m,sap.makit"
data-sap-ui-theme="sap_mvi"></script>
Second special part is an initialization of Google Maps API. Of course you need to get your own API key and use it instead of YOUR_APP_KEY.
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_APP_KEY&sensor=false"
type ="text/javascript"></script>
Third special part is calling own initialisation logic, which is placed in app.js file.
<script type="text/javascript" src="j/app.js" ></script>
Fourth special part if a small hack to set the right map size (fill all available space). We define an own css class, which fills all available space.
<style>
.myMap {
height: 100%;
width: 100%
}
</style>
This hint is taken from Google API documentation.
The last part is a body – nothing special.
3. app.js
app.js file is very simple and has just an initialisation part.
var oApplication = {};
sap.ui.localResources("v");
sap.ui.xmlview("appView", "v.appView").placeAt("content");
Here a default aplication view appView loaded according ro MVC Concept of SAPUI5 Mobile Applications
4. appView
appView consists of 2 files: view definition as xml (appView.view.xml) and view controller as js (appView.controller.js).
Here is content of these files
appView.view.xml
<core:View controllerName="v.appView"
xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns:html="http://www.w3.org/1999/xhtml">
<App id="appMaps">
<mvc:XMLView id="mainView" viewName="v.mainView"></mvc:XMLView>
</App>
</core:View>
appView.controller.js
sap.ui.controller("v.appView", {
onInit : function() {
// remember the App Control
oApplication = this.getView().byId("appMaps");
}
});
View definition just uses a simple view mainView with a content.
5. mainView
mainView will have following controls: an input field where you can enter an address, button for submitting search and finally a place for the map.
Here is a view definition.
mainView.view.xml
<core:View height="100%" controllerName="v.mainView"
xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns:html="http://www.w3.org/1999/xhtml">
<Page id="mainPage" enableScrolling="false" title="GMaps">
<VBox fitContainer="true" justifyContent="Center" alignItems="Center">
<HBox fitContainer="true" justifyContent="Center" alignItems="Center">
<Input id="inpSearch" editable="true" value="" maxLength="80"/>
<Button id="bntSearch" text="Search" tap="actSearch" />
</HBox>
<HBox id="map_canvas" fitContainer="true" justifyContent="Center" alignItems="Center" />
</VBox>
</Page>
</core:View>
and here is a controller.
mainView.controller.js
sap.ui.controller("v.mainView", {
onInit: function () {
this.getView().byId("map_canvas").addStyleClass("myMap");
},
onAfterRendering: function () {
if (!this.initialized) {
this.initialized = true;
this.geocoder = new google.maps.Geocoder();
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(this.getView().byId("map_canvas").getDomRef(),
mapOptions);
}
},
actSearch: function () {
var map = this.map;
var address = this.getView().byId("inpSearch").getValue();
this.geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
});
There are 3 methods implemented here:
onInit – is an initialization of the view – apply a hack from Default.cshtml
onAfterRendering – is an initialization of Google Maps object
actSearch – perform search with the entered address
That’s all
Hi Konstantin,
Thanks for such a helpful blog, i am doing everything exactly as you describe here but still I can't display google map, I am using HANA XS Engine, do you think this problem is because of HANA XS Engine?
Thanks and best regards.
Fahad
Hi Fahad,
unfortunatelly, I do not know how HANA XS works. Do you have public link to your application?
May be another thing...
if you use...
You have to replace YOUR_APP_KEY with your own application key for google maps.
Best Regards
Konstantin
Hi Konstantin,
No unfortunately I don't have public link to the APP, and I changed the google map api link as you described but still it's not working : (
But many thanks for your support.
Fahad
Hi Fahad,
may be just try to use integerated js-debugger in your browser to check for errors.
Best Regards
Konstantin
Hi Konstantin,
I have tried your method. But nothing is getting displayed on the page even search input and button. If I remove the code in "onAfterRendering " then I am able to see search input and button. If add the code given in the method "onAfterRendering " search input and button are getting invisible. Can you please on this. Thanks in advance.
Hi Ravi,
Which device do you use for testing?
Best Regards
Konstantin
Thanks for you reply.
I am testing on desktop only with "?sap-ui-xx-fakeOS=ios" parameter.
Hi Ravi,
which Browser do you use.
I have tried with following:
IE9 - does not work at all
Firefox - Map is not shown
Chrome - works fine
Safari - works fine
iOS - works fine
Hi Konstantin Anikeev,
I am testing in chrome only.
Hi Ravi,
have you checked console output?
Press F12 in chrome and check console output
Best Regards
Konstantin
Hi Konstantin,
I checked it already, not getting any error or warning. Its displaying nothing.
Thanks
Ravi
Hm... that's strange. I've testen on 3 different PC's and Mac. For me works fine.
Do you have DOM Objects loaded?
Hi Konstantin,
Image is not visible. Is there any other link to load google maps api?
Hi Ravi,
you can find a lot of information on official Google Maps API Reference site.
https://developers.google.com/maps/documentation/javascript/tutorial
Best Regards
Konstantin
Hi Konstantin,
When I create a Map with the following style i can't see the map
<style>
.myMap {
height: 100%;
width: 100%
}
</style>
but when I change it to a size in pixels
<style>
.myMap {
height: 350px;
width: 400px
}
</style>
then i see the map. But in this case the map size is fixed and when for example I flip my IPad the map size is not changing with the screen size. Do you know how to solve this sizing problem so that the size of map changes as the screen size changes.
Thanks and best regards.
Fahad
Hi Fahad,
I suppose you does not use mentioned example 1 to 1, but your own view.
If it is so - you should pay attention, that your container for google maps must have width and height. For example if you use
<div id="1"><div id="2"></div></div>
and set the class for div2 width and height = 100% - it will show nothing, because div1 is empty and has width and height = 0px. 100% from 0px is 0px.
But if you set div2 width=400px; height=350px, then div2 will stretch div1 according to the size.
Please pay attention to your containers.
Best Regards
Konstantin
Very useful blog Konstantin. Your sample works great and I am trying to extend what you've done by adding an infowindow to the marker. I add this code in mainView.controller.js, in the actSearch function, so the block of code now looks like this:
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
// add info window
var contentString = 'hello world';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
} else {...
However, the marker is not clickable and no info window appears. I can get info windows to work fine on a mobile device using the plain Google samples, so perhaps I must be doing something wrong with the addListener().
And ideas?
Thanks, Kevin.
Hi Kevin,
how do you test it? It works fine for me on iPhone.
But does not work on MacBrowser even with ?sap-ui-xx-fakeOS=ipad
Regards
Konstantin
Thanks Konstantin you are right. I got so used to testing in Chrome on my laptop with ?data-sap-ui-xx-fakeOS=ios I did not consider it could be browser/fake OS setting specific.
So yes, info windows do work fine in Safari on an actual iPad and iPhone.
They don't work on Windows 7 Chrome with the fake OS setting.
Hello Konstantin,
is it possible to do your google maps project with server side javascript, so that for example the actSearch function runs on server side Javascript within the XS Engine. We tried to realize that, but the we get errors like "google was used before it was defined". We assume that on server side we have to import the google maps API, but that didn't work. Do you have an idea about that?
Thanks & Regards,
Marco
Hi Marco,
actually only https://maps.googleapis.com/maps/api/js?key=YOUR_APP_KEY&sensor=false
is a must.
Rest files can be keeped on server side, i.e. XS engine.
Regards
Konstantin
Hi Konstantin,
thanks for the fast reply. But if we integrate only the google maps api on HTML and then run code in an server side Javascript file, it says "Google was defined before used" and things like that. So the code of the google maps api can't be understand on server-side. Do you know a workaround for that?
Regards, Marco
Hi Marco,
I haven't got, what you mean with server side. Do you use a node.js and try to perform code there? Then, I suppose, you do not have onAfterRendering event, where the map initialized.
Try to set a breakpoint there.
Regards
Konstantin
Hi Konstantin,
we sended you an email. Would be a great help for us, if you could have a short look on it!
Thanks, Regards,
Marco
Hi,
Thanks for sharing! Really useful!
Kind regards,
Wouter
Hi,
I have followed the same approach but getting bellow error.
Uncaught TypeError: Cannot set property 'position' of undefined
Please help
Thanks,
JP
I am new to this can you please tell me how to find my api?
Hi
How to modify code to include autocomplete places as well
hi Kontantin,
i am using two types of maps in my app.google maps as well as baidu. i need to put the api in manifest but the problem is after refresh the key get disappear and map also get disappear.please can you suggest something how to put the api
how Auto search will perform to input field for above map........
Hi Priya,
the search functionality is placed in the function actSearch.
Best Regards
Konstantin
HI,
I was able to render map on my SAP UI5 Desktop app Successfully.
But now i am trying to create apk of it through android studio.
when i try to run the app through android studio on android emulator its shows my application launch page but map is not rendered,instead of map it shows me a blank space.
I am attaching the screenshots for both Desktop & Android Emulataor.
Kindly help me out.
Desktop
Android Studio Emulator
Thanks
Rahul Mantoo
Hi,
I have gone through the steps, used google key but for this example Google api is required to be included?.
if yes then please let me know, where I can get it and how I can use it.
Hi Konstantin Anikeev,
Thanks for your blog. It is very help.
I am facing a peculiar issue.
I have a requirement in my project to make the map visible/invisible based on certain condition.
To make the map invisible, i am doing and it works fine
this.getView().byId("map_canvas").setVisible(false);
But the following code doesn't load the map again:
this.getView().byId("map_canvas").setVisible(true);
the hbox becomes available on the screen but the google map image is not visible.
Any idea what might be the issue here?
how can i implement openstreetmap that i get the address from database through backend