How to get the data of a view - sapui5

I´m using SAPUI5, I have a MasterPage and a DetailPage, in the MasterPage I have a List and when I select de Item in the List the information is displayed in the DetailPage.
In the DetailPage I have a PositiveAction, When I press the PositiveAction I need to get the Data of the DetailPage but I don't know how to do this.
My code of the Item Press
onPoSelect : function(oEvent) {
var oListItem = oEvent.getParameter('listItem');
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("DetailPanel", {
invoicePath: oListItem.getBindingContext("solped").getPath().substr(1)
});
},
My code in the DetailPanel
onInit: function (){
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("DetailPanel").attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function (oEvent) {
this.getView().bindElement({
path: "/" + oEvent.getParameter("arguments").invoicePath,
model: "solped"
});
},
The line "oEvent.getParameter("arguments").invoicePath,"
returns this.
Invoices(CustomerName='Alfreds Futterkiste',Discount=0f,OrderID=10702,ProductID=3,ProductName='Aniseed Syrup',Quantity=6,Salesperson='Margaret Peacock',ShipperName='Speedy Express',UnitPrice=10.0000M)
I have the information but it is a String, How can I convert this String in an Object? Or, how else can I access the information in the view?
The image of the View
enter image description here

I assume you can already see the data of the detail in your Detail view.
You binded the data to the view by bindElement function and to retrieve them back in the code you are looking for "getBindingContext" function.
Create following function in your Detail controller:
// this must be connected to Button -> <Button press="onPositivePress">
onPositivePress: function(oEvent) {
var oBindingContext = this.getView().getBindingContext("solped");
// this is the path you can use to call odata service
var sPath = oBindingContext.getPath();
// this is data you are looking for
var oReqData = oBindingContext.getObject();
}

You can get all the properties as an object by passing the binding path as an argument to the getProperty function of the underlying Data model.
var oModel = this.getView().getModel("solped");
var oProps = oModel.getProperty(oListItem.getBindingContext("solped").getPath());
You can then access these properties as
oProps.CustomerName;
oProps.OrderID;
...

for converting string to object see below example.
var a = "how r u";
var b = [a];
you will get object of a in b.

Related

sap.m.table multi checkbox make it READ ONLY - On Condition + SAP UI5

This is my first post to Stack, appreciate the work you guys do, amazing.
I have a sap.m.table sap ui5 and i have 4 records
out of 4, 2 are selected by default, i want to disable the preselected once based on condition.
I have tried below code but its not working, any input please?
View
/results' }" **mode="MultiSelect"**
Controller logic
//--->disable the selected department checkboxes
var tbl = that.getView().byId('idImpactTable');
var header = tbl.$().find('thead');
var selectAllCb = header.find('.sapMCb');
selectAllCb.remove();
tbl.getItems().forEach(function(r) {
var obj = r.getBindingContext("impactModel").getObject();
var oStatus = obj.COMPLETED;
var cb = r.$().find('.sapMCb');
var oCb = sap.ui.getCore().byId(cb.attr('id'));
if (oStatus === "X") {
oCb.setSelected(true);
oCb.setEnabled(false);
} else {
oCb.setEnabled(false);
}
});
Multiselect Mode Table - Make selected check box read only
Last time I tried this I found it easiest to use the updateFinished event on the table, and then use an internal property of the column list item, like so:
onTableUpdateFinished: function (oEvent) {
oEvent.getSource().getItems().forEach(function (item) {
var data = item.getBindingContext().getObject();
item._oMultiSelectControl.setEnabled(!data.IsEnabled); //whatever your check is
});
}
You'll have to find a way to keep them disabled though when using the Select All checkbox at the top of the table. I ended up extending sap.m.Table to accomplish that, there might be easier ways...
My extension is like this
sap.ui.define([
"sap/m/Table"
], function(Control) {
return Control.extend("myapp.controls.MyTable", {
updateSelectAllCheckbox: function(oEvent) {
if (this._selectAllCheckBox && this.getMode() === "MultiSelect") {
var aItems = this.getItems();
var iSelectedItemCount = this.getSelectedItems().length;
var iSelectableItemCount = aItems.filter(function(oItem) {
//standard table does not check if the item is enabled
return oItem.getSelected() || oItem._oMultiSelectControl.getEnabled();
}).length;
// set state of the checkbox by comparing item length and selected item length
this._selectAllCheckBox.setSelected(aItems.length > 0 && iSelectedItemCount === iSelectableItemCount);
}
}
});
});
And just the standard renderer
sap.ui.define([
"sap/m/TableRenderer"
], function(Control) {
return Control.extend("myapp.controls.MyTableRenderer", {
});
});
I suppose I could have extended the ColumnListItem but that was more effort than I wanted to put into the table extension
I have managed to find the solution, please find sample code to achieve.
//--->disable the selected department checkboxes
var tbl = that.getView().byId("idImpactTable");
var header = tbl.$().find("thead");
var selectAllCb = header.find(".sapMCb");
selectAllCb.remove();
var aItems = that.byId("idImpactTable").getItems();
//---> Check individual item property value and select the item
aItems.forEach(function(oItem) {
debugger;
//---> If using OData Model items Binding, get the item object
var mObject = oItem.getBindingContext().getObject();
var sPath = oItem.getBindingContextPath();
var completed = oItem.oBindingContexts.impactModel.getProperty("COMPLETED");
//--->get the id of Multi Checkbox
var cb = oItem.$().find(".sapMCb");
var oCb = sap.ui.getCore().byId(cb.attr("id"));
if (completed === "X") {
oCb.setEditable(false);
oItem.setSelected(true);
oItem.getCells()[4].setEnabled(false);
} else {
oItem.setSelected(false);
}
});
Thank you,
Jacob.Kata
//--->disable the selected department checkboxes
var tbl = that.getView().byId('idImpactTable');
tbl.getItems().forEach(function(r) {
// this makes the trick --->
var oMultiSelCtrl = r.getMultiSelectControl();
oMultiSelCtrl.setDisplayOnly( true );
});

Smart table's property initiallyVisibleFields + ODataModel

I used SmartTable with the property initiallyVisibleFields. I bound ODataModel to it. The problem is when I want to show all fields of ODataModel, e.g. after I click on SmartTable's row and try to display it in the dialog. I just see fields from initiallyVisibleFields property. It looks like ODataModel is filtered with initiallyVisibleFields property.
I was thinking about JSONModel where I put copy of ODataModel before it is bind to SmartTable, but I am planning to use SmartFilterBar, so index of shown data in the table will be changed after filtering. So I can not simply pull data from JSONModel. I can still filter data from JSONModel based on the fields I get from
ODataModel filtered with initiallyVisibleFields but there I can still get different data, because there can be differences in the fields which are hidden.
Please, can you advice me how to solve this issue?
Thanks for any tips.
...
return Controller.extend("ABC.View1", {
oDialog: null,
onInit: function() {
var oModel, oView;
oModel = new ODataModel("/sap/opu/odata/sap/ABC/", {
useBatch: false
});
oView = this.getView();
oView.setModel(oModel);
this._createSmartTable();
},
_createSmartTable: function() {
var oSmartTable = new SmartTable('idSmartTable',{
entitySet: "ABCListSet",
tableType: "ResponsiveTable",
sStyleClass: "sapUiResponsiveContentPadding",
initiallyVisibleFields: "A,B,C,D",
showRowCount: false,
enableAutoBinding: true,
demandPopin: false,
useVariantManagement: false,
useExportToExcel: false,
useTablePersonalisation: true,
});
// Register event row click
var that = this;
var oTable = oSmartTable.getTable();
oSmartTable.attachDataReceived(function() {
var aItems = oTable.getItems();
if (aItems.length === 0) return;
$.each(aItems, function(oIndex, oItem) {
oItem.detachPress(that._createDialog);
oItem.setType("Active");
oItem.attachPress(that._createDialog);
});
});
var oVBox = new VBox();
oVBox.addItem(oSmartTable);
var oPage = this.getView().byId("idPage");
oPage.addContent(oVBox);
},
_createDialog: function(oEvent) {
//HERE I the oEvent has data filtered by initiallyVisibleFields property of Smarttable.
},
});
...
Do I understand you correctly that you want to show the complete entry in a dialog? The SmartTable uses $select statements to only load the fields of an entity that are also shown in the table. If you want to load all, I think you should add them in the requestAtLeast property.

Loading a model with Name in SAPUI5

I am trying to load models into a view. i am able to load the model when i do not give any name for the model like:-
sap.ui.getCore().byId("mao").setModel(oModel);
But the model is not set to view if i give like the below. I am not getting any error also
sap.ui.getCore().byId("mao").setModel(oModel,"myModel");
I am using load data to load my data
var oModel = new sap.ui.model.json.JSONModel();
oModel.loadData(servicePath);
sap.ui.getCore().byId("mao").setModel(oModel);
Try this:
var oModel = new sap.ui.model.json.JSONModel();
oModel.loadData(servicePath);
var oController = this;
oModel.attachRequestCompleted(function() {
var data = oModel.getData();
oController.getView().setModel(data, "namedModel");
});
Then you can call like so:
this.getView().getModel("namedModel");
Your binding paths in the view should also be adjusted for named model binding. Details please see
at documentaion regarding the binding path.
The best way to set a model to a view is by defining them in Component.js file or if you are using 1.33 and above version then define the model in manifest.json file.
Set Model in Component.js file:
Define the model init method as shown below:
sap.ui.define(['jquery.sap.global', 'sap/ui/core/UIComponent'],
function(jQuery, UIComponent) {
"use strict";
var Component = UIComponent.extend("samples.components.sample.Component", {
metadata : {
}
init: function() {
var sServiceUrl = 'example/servie';
var oModel = new sap.ui.model.odata.ODataModel (sServiceUrl, true);
this.setModel (oModel, "modelName");
}
});
return Component;
});
Set the model in manifest.json file
https://openui5.hana.ondemand.com/#docs/guide/be0cf40f61184b358b5faedaec98b2da.html
Now this model will be available in any controller and you can access the model as mentioned below:
var oModel = this.getView().getModel("modelName");
this._sValidPath =jQuery.sap.getModulePath("OpenUI.c", "/name.pdf");
this._oModel = new JSONModel({
Source: this._sValidPath,
Title: "My Custom Title",
Height: "600px"
});
sap.ui.getCore().setModel(this._oModel,"mainModel2");
sap.ui.getCore().byId("mao").setModel(oModel);
But the model is not set to view if i give like the below.
You did not bind this to the View you bound it to the core.
Remove the .byId("mao") and it should work.
var oModel = new sap.ui.model.json.JSONModel();
oModel.loadData(servicePath);
sap.ui.getCore().setModel(oModel, "myModelName");
Read Model:
var oMyModel = sap.ui.getCore().getModel("myModelName");
sap.ui.getCore().byId("mao").setModel("myModel") means you want to get a object by the ID "mao" and assign a model to the object.
This is how the view binding works:
this.getView().setModel(oModel, "myModelName");
var oMyModel = this.getView().getModel("myModelName");
On the OpenUI5 site theres a nice developer walkthrough check this out:
https://openui5beta.hana.ondemand.com/#docs/guide/70ef981d350a495b940640801701c409.html

setBusy not executing

I have setBusy exucuting elsewhere in my application, but why not here....
This is reading in my site details, so without the setbusy the page looks like it's doing nothing.
_onRouteMatched: function (oEvent) {
//initialise display
var view = this.getView();
view.setBusy(true);
view.byId("shopInput").setValue("");
view.byId("effectiveDateFrom").setValue("");
view.byId("shop24Hrs").setSelected(false);
view.byId("shopClosed").setSelected(false);
view.byId("createNext").setVisible(false);
view.byId("createSubmit").setVisible(false);
//view.byId("createSave").setVisible(false);
// initialise the store view model
var oModel = this.getModel("site");
this.getModel().read("/SiteSet", {
success: function (oData) {
var oSiteData = oModel.getData();
oSiteData.Sites = oData.results;
oModel.setData(oSiteData);
}.bind(this)
});
view.setBusy(false);
},
Any Ideas?
Actually your code sets busy but resets it right away. The read method is asynchronous. You have to reset busy inside the success callback function (it could be a good idea to reset it in an error callback too).
_onRouteMatched: function (oEvent) {
//initialise display
var view = this.getView();
view.setBusy(true);
view.byId("shopInput").setValue("");
view.byId("effectiveDateFrom").setValue("");
view.byId("shop24Hrs").setSelected(false);
view.byId("shopClosed").setSelected(false);
view.byId("createNext").setVisible(false);
view.byId("createSubmit").setVisible(false);
//view.byId("createSave").setVisible(false);
// initialise the store view model
var oModel = this.getModel("site");
this.getModel().read("/SiteSet", {
success: function (oData) {
var oSiteData = oModel.getData();
oSiteData.Sites = oData.results;
oModel.setData(oSiteData);
view.setBusy(false);
}.bind(this),
error: function(){
view.setBusy(false);
}
});
},
Generally when using setBusy() you should mind this points:
Per default the busy indicator is displayed 1000 milliseconds after setBusy(true). There is a setBusyIndicatorDelay() function to control that delay (can be set to 0).
The busy indicator is always created deferred (using setTimeout()). JavaScript is singlethreaded. So if your code after calling setBusy() blocks, the busy indicator will not be displayed until your code has finished and the control flow is returned to the event loop. So don't try this: setBusy(true); model.loadData("/data", false /*synchronous*/); setBusy(false);
You can create a busy dialog object and then use open and close function in the success call back and error call back respectively. Please have a look at the code:-
_onRouteMatched: function (oEvent) {
//initialise display
var busyDialog= new sap.m.BusyDialog;
view.byId("shopInput").setValue("");
view.byId("effectiveDateFrom").setValue("");
view.byId("shop24Hrs").setSelected(false);
view.byId("shopClosed").setSelected(false);
view.byId("createNext").setVisible(false);
view.byId("createSubmit").setVisible(false);
//view.byId("createSave").setVisible(false);
// initialise the store view model
var oModel = this.getModel("site");
busyDialog.open();
this.getModel().read("/SiteSet", {
success: function (oData) {
busyDialog.close();
var oSiteData = oModel.getData();
oSiteData.Sites = oData.results;
oModel.setData(oSiteData);
}.bind(this)
});
busyDialog.close();
},

How to init/Re-Init Page or trigger onBeforeRendering again?

I have a main screen with a tile the user can press to go to another page. The onInit for this second page works fine in getting/setting the model and the data shows correctly.
If I 'go back' to the first page (after I have made changes on the second screen), and then click the tile to go to the second page, it doesn't call the onInit this second time and so the data reflects the changes that were made and not what I want (the true initialized data). I tried changing the onInit to onBeforeRedendering hoping that it would re-initialize the model/data but it doesn't seem to reset everything correctly.
Is there a way on going back to do something to force the onInit to be called the next time the page is called? I think, if I can make it so the onInit is called each time the page is called, that it would fix my problem.
Here is the portion of my controller for the onInit and 'go back'....
sap.ui.define([
'sap/ui/core/mvc/Controller',
'sap/ui/model/json/JSONModel',
'sap/viz/ui5/controls/common/feeds/FeedItem',
'sap/m/MessageBox',
'sap/viz/ui5/data/FlattenedDataset'
], function(Controller, JSONModel, FeedItem, MessageBox, FlattenedDataset) {
"use strict";
var ColumnController = Controller.extend("controllers.Quarter", {
onInit: function(oEvent) {
var oRouter = sap.ui.core.routing.Router.getRouter("router");
var myView = this.getView();
var today = new Date();
var year = today.getFullYear();
var yr = year.toString();
var mnth = today.getMonth();
var qtr = Math.floor((mnth / 3));
this.makeYearList(yr);
var mthis = this;
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({
yr: yr
});
sap.ui.getCore().setModel(oModel);
myView.byId("mySelectMenu").setSelectedKey(yr);
myView.byId("mySelectMenu").attachChange(function() {
yr = this.getSelectedKey();
mthis.checkYr(yr, qtr);
mthis.recList(myView, yr, qtr);
});
myView.byId("selQtr").attachChange(function() {
qtr = this.getSelectedKey();
mthis.checkYr(yr, qtr);
mthis.recList(myView, yr, qtr);
});
oRouter.attachRouteMatched(function(oEvent) {
mthis.checkYr(yr, qtr);
mthis.recList(myView, yr, qtr);
});
},
goBack: function() {
var oHistory = sap.ui.core.routing.History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
var oView = this.getView();
if (sPreviousHash) {
window.location.replace("#/" + sPreviousHash);
} else {
window.location.replace("#");
}
},
});
return ColumnController;
});
I'd appreciate any advice.
Put the logic to reset the model data into the route matched handler.
The better way to overcome this problem is, use shell for your page one and two. Shell will automatically destroy your content(if you are in page two then page one content would be destroyed and vice versa). else, you need to destroy the content manually to overcome duplicate id issue, u need to destroy by your own and call the controller wherever you want.