Skip to Content
0
Jan 24, 2020 at 01:05 AM

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

291 Views

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]));

					},