cancel
Showing results for 
Search instead for 
Did you mean: 

Displaying a route on a GeoMAP using an Odata service in a SAPUI5 app

former_member656097
Discoverer
0 Kudos

Hi,

I am developing a SAPUI5 application that displays routes on a geoMAP.

I followed this tutorial 'https://embed.plnkr.co/kEzGKiJtuyPKGru5XdL0/' that takes a local JSON data model.

In my app I have established an odata service: which consists of two entity sets called 'Trips' and 'Trip Details'. The 'Trips' consists of trip id's and association to the 'Trip Details' that consists of latitude and longitude values of that trip. The JSON of odata service kind of looks like this:

{
  "d": {
    "results": [
      {
        "__metadata": {
          "type": "public.*******.trip_idsType",
          "uri": "https://*****services/data.xsodata/trip_ids('00000')"
        },
        "TRIP_ID": "00000",
        "TRIP_DETAILS": {
          "__deferred": {
            "uri": "https:/******/services/data.xsodata/trip_ids('00000')/TRIP_DETAILS"
          }
        }
      }, .....

}

For my application I am using master detail template and I want to display the respective map of the trip selected in detail view. The map configuration is provided in detail view controller.

Below is the map configuration required for plotting route from a local json data model as per the tutorial.

The problem I am having is in specifying the 'path' value in 'oSpotsCollection' and 'oRouteCollection' because I am now using an oData service and not a local JSON model like shown in tutorial.

Could someone please help me in specifying the path value as per my use case?

// MAP CONFIGURATION AS PER TUTORIAL
			var oMapConfig = {...}

			var oSpotTemplate = new sap.ui.vbm.Spot({
				position: {
					parts: [{
						path: "d/results/LATITUDE"
					}, {
						path: "d/results/LONGITUDE"
					}],
					formatter: function (lat, lon) {
						return (lon + ";" + lat);
					}
				},
				type: sap.ui.vbm.SemanticType.Default,
				text: '{SPEED}'
			});


			var oSpotsCollection = new sap.ui.vbm.Spots({
				items: {
			----->		path: "/d/results",
					template: oSpotTemplate
				}
			});



			var oRouteTemplate = new sap.ui.vbm.Route({
				position: {
					path: "d",
					formatter: function (arrayOfPoints) {
						var route = [];
						var context = this.getBindingContext();
						var list = context.oModel.aBindings[0].oList.d.results;
						for (var i = 0; i < list.length; i++) {
							var lat = list[i].LATITUDE;
							var lon = list[i].LONGITUDE;
							route.push(lon + ";" + lat + ";0");
						}
						return (route.join(';'));
					}
				},
				colorBorder: "rgb(0, 0, 230)",
				color: "rgb(150, 186, 230)",
				tooltip: "This is my Route"
			});


			var oRouteCollection = new sap.ui.vbm.Routes({
				items: {
		------->		path: "/",
					template: oRouteTemplate
				}
			});


			//UNCOMMENT TO PLOT THE DATA AS SPOTS
			//oGeoMap.addVo(oSpotsCollection);
			oGeoMap.addVo(oRouteCollection);


This is the detail view controller just like in the template:

onInit: function () {
			// Model used to manipulate control states. The chosen values make sure,
			// detail page is busy indication immediately so there is no break in
			// between the busy indication for loading the view's meta data
			var oViewModel = new JSONModel({
				busy: false,
				delay: 0,
				lineItemListTitle: this.getResourceBundle().getText("detailLineItemTableHeading")
			});
			this.getRouter().getRoute("object").attachPatternMatched(this._onObjectMatched, this);
			this.setModel(oViewModel, "detailView");
			this.getOwnerComponent().getModel().metadataLoaded().then(this._onMetadataLoaded.bind(this));
			


		},


		_onObjectMatched: function (oEvent) {
			var sObjectId = oEvent.getParameter("arguments").objectId;
			this.getModel("appView").setProperty("/layout", "TwoColumnsMidExpanded");
			this.getModel().metadataLoaded().then(function () {
				var sObjectPath = this.getModel().createKey("trip_ids", {
					TRIP_ID: sObjectId
				});
				this._bindView("/" + sObjectPath);
			}.bind(this));
		},

		_bindView: function (sObjectPath) {
			// Set busy indicator during view binding
			var oViewModel = this.getModel("detailView");


			// If the view was not bound yet its not busy, only if the binding requests data it is set to busy again
			oViewModel.setProperty("/busy", false);


			this.getView().bindElement({
				path: sObjectPath,
				parameters: {
					expand: "segments"
				},
				events: {
					change: this._onBindingChange.bind(this),
					dataRequested: function () {
						oViewModel.setProperty("/busy", true);
					},
					dataReceived: function () {
						oViewModel.setProperty("/busy", false);
					}
				}
			});
		},


		_onBindingChange: function () {
			var oView = this.getView(),
				oElementBinding = oView.getElementBinding();


			// No data for the binding
			if (!oElementBinding.getBoundContext()) {
				this.getRouter().getTargets().display("detailObjectNotFound");
				// if object could not be found, the selection in the master list
				// does not make sense anymore.
				this.getOwnerComponent().oListSelector.clearMasterListSelection();
				return;
			}


			var sPath = oElementBinding.getPath(),
				oResourceBundle = this.getResourceBundle(),
				oObject = oView.getModel().getObject(sPath),
				sObjectId = oObject.TRIP_ID,
				sObjectName = oObject.TRIP_ID,
				oViewModel = this.getModel("detailView");


			this.getOwnerComponent().oListSelector.selectAListItem(sPath);


			oViewModel.setProperty("/shareSendEmailSubject",
				oResourceBundle.getText("shareSendEmailObjectSubject", [sObjectId]));
			oViewModel.setProperty("/shareSendEmailMessage",
				oResourceBundle.getText("shareSendEmailObjectMessage", [sObjectName, sObjectId, location.href]));

					},

Accepted Solutions (0)

Answers (1)

Answers (1)

devendervb
Contributor
0 Kudos

Hi bhawna333 ,

Seems you have miss understood aggregation binding at

var oSpotsCollection =newsap.ui.vbm.Spots({
				items:{----->		path:"/d/results",
					template: oSpotTemplate
				}});

for me it looks fine, relative to json file posted.

now oSpotTemplate should be path : 'd/results/' not required as it is already mentioned in it's parent

var oSpotTemplate =newsap.ui.vbm.Spot({position:{
					parts:[{
						path:"LATITUDE"},{
						path:"LONGITUDE"}],
					formatter:function(lat, lon){return(lon +";" + lat);}},type:sap.ui.vbm.SemanticType.Default,text:'{SPEED}'});

Just check...

also check similar issue with other aggregetion.

former_member656097
Discoverer
0 Kudos

Thank you for your reply. I am fairly new to SAPUI5 and that's why a bit confused to make it work. Like I said, I faced no issues with a simple local JSON file. The issue is with oData service. I don't understand how to specify the path value in 'oSpotsCollection' and 'oRouteCollection'.

For local json file the path values were simple (path: "/d/results" and path:"/"). Now this odata service has '_deferred URI' that takes to associated 'Trip Details' entity set for a particular TRIP_ID. Problem is I don't know how to specify path for the bounded 'Trip_Details' entity set so that I can access the latitude and longitude values.

(I am sorry if the question looks repetitive to what I asked, I just want the same results like I got for local json data model)

This is how oData service looks like:

https://******/data.xsodata/trip_ids/?$format=json

{
  "d": {
    "results": [
      {
        "__metadata": {
          "type": "public.*******.trip_idsType",
          "uri": "https://*****services/data.xsodata/trip_ids('00000')"
        },
        "TRIP_ID": "00000",
        "TRIP_DETAILS": {
          "__deferred": {
            "uri": "https:/******/services/data.xsodata/trip_ids('00000')/TRIP_DETAILS"
          }
        }
      }, .....

}

https:/************/data.xsodata/trip_ids('00000')/TRIP_DETAILS/?$format=json

{
  "d": {
    "results": [
      {
        "__metadata": {
          "type": "public.******",
          "uri": "https:/*******/data.xsodata/trip_ids('00000')"
        },
        "ID": "00***",
        "TRIP_ID": "00000",
        "SEGMENT_ID": "0*****",
        "LATITUDE": "44.8527717590332",
        "LONGITUDE": "20.38993072509765",
        "TIMESTAMP": "/Date(1562947105000)/",
        "SPEED": "21.6"
      },