Skip to Content
0

How to propely bind data to VizFrame when it changes dynamically?

Dec 20, 2017 at 07:59 AM

484

avatar image
Former Member

I have one JSON which I get by calling server. Then I have tried set oData model but it causes error in sap-ui-core.js:335 :

Uncaught(in promise)TypeError:Cannot read property'indexOf' of undefined

I tried to do it dynamically. When I hard code this json it works well. But issue occurs during changing data. I get a response with data from the server but binding is not working.

Should I try with any kind of refreshing VizFrame? (oVizFrame.vizUpdate() with data inside doesn't work).

I am using UI5 1.38 version.

Some help will be very appreciated. Thanks in advance.

10 |10000 characters needed characters left characters exceeded
* Please Login or Register to Answer, Follow or Comment.

3 Answers

Best Answer
Irfan Gokak Dec 21, 2017 at 04:53 PM
0

Hi,

This is complete code which I'm using to update viz chart. Please check from initial to end.

// In View ---------------------------------
<viz:VizFrame id="idVizFrame" uiConfig="{applicationSet:'fiori'}" height='100%' width="100%" vizType='column'>
	<viz:dataset>
		<viz.data:FlattenedDataset data="{ChartMdl>/Chart}">
			<viz.data:dimensions>
				<viz.data:DimensionDefinition name="Full Year" value="{ChartMdl>Month}"/>
			</viz.data:dimensions>
			<viz.data:measures>
				<viz.data:MeasureDefinition name="Sales Qty" value="{ChartMdl>SalQty}"/>
				<viz.data:MeasureDefinition name="Forecast Qty" value="{ChartMdl>ForQty}"/>
			</viz.data:measures>
		</viz.data:FlattenedDataset>
	</viz:dataset>
	<viz:feeds>
		<viz.feeds:FeedItem id='valueAxisFeed1' uid="valueAxis" type="Measure" values="Sales Qty"/>
		<viz.feeds:FeedItem id='valueAxisFeed' uid="valueAxis" type="Measure" values="Forecast Qty"/>
		<viz.feeds:FeedItem id='categoryAxisFeed' uid="categoryAxis" type="Dimension" values="Full Year"/>
	</viz:feeds>
</viz:VizFrame>

// In Controller -----------------------------------------
// Initial binding ----------------------------------------
_setChartData : function(){
	Format.numericFormatter(ChartFormatter.getInstance());
        var formatPattern = ChartFormatter.DefaultPattern;
        var oVizFrame = this.oVizFrame = this.getView().byId("idVizFrame");
        oVizFrame.setVizProperties({
                plotArea: {
                    dataLabel: {
                        formatString:formatPattern.SHORTFLOAT_MFD2,
                        visible: false
                    }
                },
                title: {
                    visible: false,
                    text: 'Company'
                }
        });
        var oPopOver = this.getView().byId("idPopOver");
        oPopOver.connect(oVizFrame.getVizUid());
        oPopOver.setFormatString(formatPattern.STANDARDFLOAT);
        var data = [{
        "Month": "Jan 2017",
        "SalQty": 3750,
        "ForQty": 0,
        "SalVal": 25250,
        "ForVal": 0
    },{
        "Month": "Feb 2017",
        "SalQty": 3500,
        "ForQty": 0,
        "SalVal": 24500,
        "ForVal": 0
    },{
        "Month": "Mar 2017",
        "SalQty": 3500,
        "ForQty": 0,
        "SalVal": 24500,
        "ForVal": 0
    }];
    var oJson = new sap.ui.model.json.JSONModel({"Chart" : data});
    oVizFrame.setModel(oJson, "ChartMdl");
}

// Update chart data
updateChart : function(oEvent) {
        var data = [{
        "Month": "Jan 2017",
        "SalQty": 3750,
        "ForQty": 0,
        "SalVal": 25250,
        "ForVal": 0
        },{
        "Month": "Feb 2017",
        "SalQty": 3500,
        "ForQty": 0,
        "SalVal": 24500,
        "ForVal": 0
    },{
        "Month": "Mar 2017",
        "SalQty": 3500,
        "ForQty": 0,
        "SalVal": 24500,
        "ForVal": 0
    }];
        var oJson = new sap.ui.model.json.JSONModel({"Chart" : data});
	oVizFrame.setModel(oJson, "ChartMdl");
}

THat's it!!!! This is only code I'm using. Please check.

Show 6 Share
10 |10000 characters needed characters left characters exceeded
Former Member
So what is wrong with this code? I have followed your suggestions but it gaves me blank VizFrame. 



onInit: function () {
var oVizFrame = sap.ui.getCore().byId("idVizFrame");
var jsonModel = this.callToGateway();
oVizFrame.setModel(jsonModel, "ChartMdl");
},
callToGateway: function () {
//Set Chart Title
var oVizFrame = sap.ui.getCore().byId("idVizFrame");
//Calling Gateway
var serviceUrl = "/sap/opu/odata/SAP/ZKPITEST_SRV";
var oModel = new sap.ui.model.odata.v2.ODataModel(serviceUrl, false);
var oYearSelect = sap.ui.getCore().byId("yearSelect");
var oMonthSelect = sap.ui.getCore().byId("monthSelect");
var sPath = "/AVGMINMAXCalcSet";
var servers = ["LB", "tomcat6", "tomcat7", "tomcat8"];
if (oYearSelect.fireEvent() || oMonthSelect.fireEvent()) {
for (var i = 0; i < servers.length; i++) {
var finalFilter = monthFilter.concat(" and ServerName eq " + "'" + servers[i] + "'");

oModel.read(sPath, {
urlParameters: {
"$filter": finalFilter,
},
success: function (oData, oResponse) {
oDataResults = oData.results[0];
delete oDataResults.LogDate;
delete oDataResults.__metadata;
oDataArr.push(oDataResults);
},
});
}
var jsonModel = new sap.ui.model.json.JSONModel({
"Chart": oDataArr
});
oVizFrame.setModel(jsonModel, "ChartMdl");
return jsonModel;
}
},
0

Please check the model name in below tag.

<viz.data:FlattenedDataset data="{ChartMdl>/Chart}">
0

If you still have issue you can contact me through LinkedIn.

0
Former Member

The problem is when I get data from server it seems that my json is null. But when I show it in console.log some lines after oModel.read() it has values.

0

put this statement inside the success function of read call.

oVizFrame.setModel(jsonModel, "ChartMdl");
0
Former Member

Putting statatement inside success function doesn't work due to the fact oModel had a default value about Batch calling. So the problem was that my 4 GET methods was called in Batch and that's why my objects inside success metod of oModel.read() has a null value.

Using method attachBatchRequestCompleted outside of oModel.read() works properly.

oModel.attachBatchRequestCompleted(oModel, function(){
var jsonModel = new sap.ui.model.json.JSONModel({"Chart" : oDataArr});
oVizFrame.setModel(jsonModel, "ChartMdl");
});

Thank you so much for your effort @irfan.gokak, now everything works perfectly with your binding solution :)

0
avatar image
Former Member
Dec 26, 2017 at 07:35 AM
1

Let's say you have a oDataModel like the following

var sServiceUri = ".../abc.xsodata";

var oDataModel = new sap.ui.model.odata.v2.ODataModel(sServiceUri,true,"username","password");

you could then set it to oVizFrame like below without transfer it to JSON model beforehand.

oVizFrame.setModel(oDataModel);

When it comes to dataset update at runtime, there are 2 scenarios:

1. update dataModel only if dataset remains unchanged: you could set it to vizFrame by calling setModel directly like below without using vizUpdate. This will caure a batch call to the backend for new data request.

oVizFrame.setModel(oDataModel);

2. update dataModel AND dataset altogether: It is suggested to destroy the feeds and dataset before bounding the new ones to vizFrame

function updateDataset(){
  oVizFrame.destroyFeeds(); //clean up the feeds and dataset binding before update
  oVizFrame.destroyDataset(); 
  var oDataModel = new sap.ui.model.odata.v2.ODataModel(sServiceUri,true,"username","password");
  var nDataset = new sap.viz.ui5.data.FlattenedDataset({ 
    'dimensions' : [{'name' : 'City', 'value' : "{City}"}], 
    'measures' : [{'name' : 'Capital', 'value' : '{Capital}'}], 
    'data' : {'path' : "/businessData"} 
  }); 
  oVizFrame.setModel(oDataModel);
  var feeds = [
    new sap.viz.ui5.controls.common.feeds.FeedItem({'uid' : "valueAxis", 'type' : "Measure",'values' : ["Capital"]}), 
    new sap.viz.ui5.controls.common.feeds.FeedItem({'uid' : "categoryAxis",'type' : "Dimension",'values' : ["City"]})
  ]; 
  var properties = {....}; 
  oVizFrame.vizUpdate({ 
    'data' : nDataset, 
    'properties' : properties, 
    'feeds' : feeds 
  });
} 
Show 2 Share
10 |10000 characters needed characters left characters exceeded
Former Member

Can you check code which I have put as a answer comment in above Irfan's comment? Thanks :)

0
Former Member

Sorry, I don't really know how. :(

0
Irfan Gokak Dec 20, 2017 at 02:36 PM
0

Hi,

After getting new data set model to Chart again and refresh the model. That's how i'm also doing.

// data is updated data
var oJson = new sap.ui.model.json.JSONModel({"Chart" : data}); oVizFrame.setModel(oJson, "ChartMdl"); this.getView().getModel("AllMdl").refresh();
Show 10 Share
10 |10000 characters needed characters left characters exceeded
Former Member

Hi @irfan.gokak I have some code like this below based on your proposition and unfortunately, it's not working. Have you any suggestions on what am I doing wrong?

oModel.read(sPath, {
	urlParameters: {
		"$filter": Filter,
	},
	success: function (oData, oResponse) {
		oDataValues = oData;
		var oData = oData.results[0];
		oDataArr.push(oData);


	},
});


var jsonModel = new sap.ui.model.json.JSONModel();
jsonModel.setData(oDataArr);
sap.ui.getCore().setModel(jsonModel);


oVizFrame.setModel(jsonModel);
this.getView().getModel().refresh();
0

First of all don't set model to core. Set it at view level.

// This is core level
sap.ui.getCore().setModel(jsonModel);

// For View level this.getView().setModel(jsonModel);

// Modify your code in Controller. oModel.read(sPath, { urlParameters: { "$filter": Filter, }, success: function (oData, oResponse) { var jsonModel = new sap.ui.model.json.JSONModel({"Chart":oData.results}); oVizFrame.setModel(jsonModel, "mdlName"); }, }); // In View <viz:VizFrame id="idVizFrame" uiConfig="{applicationSet:'fiori'}" height='100%' width="100%" vizType='column'> <viz:dataset> <viz.data:FlattenedDataset data="{mdlName>/Chart}"> <viz.data:dimensions> <viz.data:DimensionDefinition name="Full Year" value="{AllMdl>Month}"/> </viz.data:dimensions> <viz.data:measures> <viz.data:MeasureDefinition name="Sales Qty" value="{AllMdl>SalQty}"/> <viz.data:MeasureDefinition name="Forecast Qty" value="{AllMdl>ForQty}"/> </viz.data:measures> </viz.data:FlattenedDataset> </viz:dataset> <viz:feeds> <viz.feeds:FeedItem id='valueAxisFeed1' uid="valueAxis" type="Measure" values="Sales Qty"/> <viz.feeds:FeedItem id='valueAxisFeed' uid="valueAxis" type="Measure" values="Forecast Qty"/> <viz.feeds:FeedItem id='categoryAxisFeed' uid="categoryAxis" type="Dimension" values="Full Year"/> </viz:feeds> </viz:VizFrame>
1
Former Member

According to your code which I have to modify in controller. I cannot do that because I have for loop which calling server 4 times and gets data and then I push it to oDataArr and next create json model.

0

Then Make a batch call first then in success do the same.

0

Using batch you can make 4 requests in a single Call. Hope I’m clear

0
Former Member

So I have to 4 times push into batchChanges results from the createBatchOperation like below, right?

var batchChanges = [];

batchChanges.push( oModel.createBatchOperation(sPath, "GET", {urlParameters: {
"$filter" : finalFilter,
}, } ) );
0

Yes. or else go to this Link

0
Former Member

Thank you. I will let know how's results going.

0

Sure!!!!!!!

0
Former Member

I got an error:

Uncaught TypeError: Cannot read property 'refresh' of undefined

After using

this.getView().getModel().refresh();
0