I'm just starting with SAP FIORI app developing.
I created simple oData model for SAP user details, I implemented two methods:
get_entityset - receives list of users with personal number and full name
get_entity - receives more details of single user (by username).
When I call the service from browser all works fine. How do I call my get_entity method when loading detail page of Master-Detail FIORI app. I used Master-Detail template from WebIDE, but only get_entitset is called and detail screen uses only set data.
How should I define the data binding (in Detail controller I guess)?
Let's assume your Entity is called User and your EntitySet is called Users. We also assume your Entity has one key field of type Edm.String called UserId and another field called FullName of type Edm.String.
var sPath = "/the/path/to/my/service";
var oModel = new sap.ui.model.odata.ODataModel(sPath);
sap.ui.getCore().setModel(oModel);
var oText = new sap.ui.commons.TextView({
text: "{FullName}"
});
oText.bindElement("/Users('MyUserId')");
oText.placeAt("content");
Since you are binding to "/Products('MyProductId')" your "get_entity" is called. Binding to "/Products" would call "get_entityset". However, a binding to "/Products" is used for tables or lists and usually not for a simple TextView (like the above example). There are many tutorials on the web and you will see that this is not as complicated as you might guess.
Related
Can I know the difference and performance when I use:
const myControl = this.getView().byId("myIDhere");
const myControl = this.byId("myIDhere");
const myControl = sap.ui.getCore().byId("myIDhere");
Which of three is best to use to perform operations on control when I use XML views in UI5 apps?
Difference between this.getView().byId and this.byId
Take a look at the source code of the this.byId method:
// sap.ui.core.mvc.Controller
Controller.prototype.byId = function(sId) {
return this.oView ? this.oView.byId(sId) : undefined;
};
As you can see, this.byId is just a shortcut for this.getView().byId. They both can be used to access controls defined in the view. E.g.:
<!-- Given -->
<Panel id="myPanel" />
myControllerMethod() {
const thatPanel = this.byId("myPanel"); // === this.getView().byId("myPanel")
},
About sap.ui.getCore().byId (Rarely used)*
The API sap.ui.getCore().byId on the other hand, awaits a fully concatenated global ID which is why you cannot simply exchange this.byId with sap.ui.getCore().byId if the target control is a view descendant.
sap.ui.getCore().byId("__xmlview0--myPanel"); // <-- Avoid concatenating ID parts!
Generally, sap.ui.getCore() should be avoided when developing UI5 applications that would be added to Fiori launchpad (FLP). I.e. when instantiating a control in the controller, instead of passing a plain string literal only (e.g. new Panel("myPanel")), use the API createId:
new Panel(this.createId("myPanel")); // makes it accessible via this.byId("myPanel")
From the topic "JavaScript Coding Issues" section "Don't create global IDs":
[...] you must not create stable IDs for your controls, fragments, or views in OpenUI5. Doing so might result in duplicate ID errors that will break your app. Especially when running together with other apps, there could be name clashes or other errors.
Use the createId() function of a view or controller instead. This is done automatically in XMLViews and JSONViews. The createId() function adds the View ID as a prefix, thus recursively ensuring uniqueness of the ID.
* One of the valid use cases for sap.ui.getCore().byId is when accessing the currently focused control of which the ID was retrieved by calling getCurrentFocusedControlId().
More about IDs
Stable IDs: All You Need to Know
For the sake of completeness: How to Access Elements from XML Fragment by ID
SAP Fiori elements guidelines
When developing Fiori elements extensions, make sure to adhere to the documented compatibility guidelines, especially regarding byId:
[...] Don't access or manipulate SAP Fiori elements' internal coding.
[...] Must not access any UI elements that are not defined within your view extensions.
⚠ Caution
If you do not adhere to this guideline, your app may not work with future SAPUI5 versions because SAP Fiori elements might exchange controls for new ones that have a different API.
I've a sapui5 application which has several controls in my page.
Such as Tables , Calendar etc.
And I've create a singe model for my page in the onInit event as follows
var viewModel = new JSONModel();
//Prepare Initial Model
viewModel.setData({
LineDetails: [],
Calendar: {},
PageMode: "add",
DateStart: new Date(),
DateEnd: new Date(),
IsHistoryAvailable: false
});
this.getView().setModel(viewModel);
What I need to do is, I've to include a Smart Table inside a dialog in this page.
The dialog will open once I click a button in the page.
How can I bind data to the smart table inside the dialog?
I only have experience of binding the model to a smart table which either declaring default model in the manifest or in the page.
But here I've already added a model to the page in the onInit event.
So how can I bind data?
Is there a way to bind smart table to a Property which included in the above declared model.
Propert name : SmartTableModel
eg :
viewModel.setData({
SmartTableModel:[]
LineDetails: [],
Calendar: {},
PageMode: "add",
DateStart: new Date(),
DateEnd: new Date(),
IsHistoryAvailable: false
});
Per default, the data you want to bind must come from an ODataModel which is the default model! In other words: you can't simply bind data from some JSONModel, and you can't bind data to a SmartTable which comes from a named model (even if it's and ODataModel).
SmartTable only works with data from an ODataModel, thus you can't work with JSonModels
Currently, SmartTable only works with dafault models (""), i.e. named model won't work
I'm afraid to tell you that what you want does not work as of today. You could use the MockerServer + annotations in your real app code (not onbly for testing) as a workaround, but I think I would avoid that. There are some other tricks as well, you could start reading here: SAP UI5 :named json model with smart table
Can I know the difference and performance when I use:
const myControl = this.getView().byId("myIDhere");
const myControl = this.byId("myIDhere");
const myControl = sap.ui.getCore().byId("myIDhere");
Which of three is best to use to perform operations on control when I use XML views in UI5 apps?
Difference between this.getView().byId and this.byId
Take a look at the source code of the this.byId method:
// sap.ui.core.mvc.Controller
Controller.prototype.byId = function(sId) {
return this.oView ? this.oView.byId(sId) : undefined;
};
As you can see, this.byId is just a shortcut for this.getView().byId. They both can be used to access controls defined in the view. E.g.:
<!-- Given -->
<Panel id="myPanel" />
myControllerMethod() {
const thatPanel = this.byId("myPanel"); // === this.getView().byId("myPanel")
},
About sap.ui.getCore().byId (Rarely used)*
The API sap.ui.getCore().byId on the other hand, awaits a fully concatenated global ID which is why you cannot simply exchange this.byId with sap.ui.getCore().byId if the target control is a view descendant.
sap.ui.getCore().byId("__xmlview0--myPanel"); // <-- Avoid concatenating ID parts!
Generally, sap.ui.getCore() should be avoided when developing UI5 applications that would be added to Fiori launchpad (FLP). I.e. when instantiating a control in the controller, instead of passing a plain string literal only (e.g. new Panel("myPanel")), use the API createId:
new Panel(this.createId("myPanel")); // makes it accessible via this.byId("myPanel")
From the topic "JavaScript Coding Issues" section "Don't create global IDs":
[...] you must not create stable IDs for your controls, fragments, or views in OpenUI5. Doing so might result in duplicate ID errors that will break your app. Especially when running together with other apps, there could be name clashes or other errors.
Use the createId() function of a view or controller instead. This is done automatically in XMLViews and JSONViews. The createId() function adds the View ID as a prefix, thus recursively ensuring uniqueness of the ID.
* One of the valid use cases for sap.ui.getCore().byId is when accessing the currently focused control of which the ID was retrieved by calling getCurrentFocusedControlId().
More about IDs
Stable IDs: All You Need to Know
For the sake of completeness: How to Access Elements from XML Fragment by ID
SAP Fiori elements guidelines
When developing Fiori elements extensions, make sure to adhere to the documented compatibility guidelines, especially regarding byId:
[...] Don't access or manipulate SAP Fiori elements' internal coding.
[...] Must not access any UI elements that are not defined within your view extensions.
⚠ Caution
If you do not adhere to this guideline, your app may not work with future SAPUI5 versions because SAP Fiori elements might exchange controls for new ones that have a different API.
Within the onBeforeRendering() function of a view how should I determine if a specific node is present in the model and modify the model to include the node if not? This question is about lazy loading of data to the model for data that will be infrequently accessed by users but would have a performance penalty if loaded with initial model data.
My use case has a list page leading to a detail page for whatever item in the list the use clicks. On the detail page is a set of tabs which expose sub-details related to the selected detail. Specifically a long text description of a the brief for a task.
The tab control leads via manifest.json style routing to display a view in the tabs content area.
This is my current working code which is within the onBeforeRendering event of the view controller:
onBeforeRendering: function(oEvent){
var sPath = this.getView().getBindingContext("Projects").getPath(); // something like /task/6
console.log('Path='+sPath)
var oModel = this.getView().getModel("Projects");
var oTask = oModel.getProperty(sPath + "/brief");
if (oTask) { // looks like /brief exists so must already have loaded the brief
// nothing to do
console.log('Use existing data')
}
else { // /brief not yet present so we need to load it up
console.log('Load new data')
oModel.setProperty(sPath + "/brief", "This is the brief...") // replace with loaddata() from server, use attachRequestCompleted to call function to modify model.
}}
Question - is this the correct approach?
Edit: Based on discussion in this question I modified my code to use an event that fires per display of the view. onBeforeRendering turned out to run without much apparent predictability - which I am sure it has but in any case I wanted a one-per-display event. Also, I fleshed out the code further but retained the basic structure and it appears to do what I wanted.
This is a valid approach. But you should think aboute following use case: What happens if the data you loaded have been changed at the backend? The JSONModel does not give you any support here as it acts dumb data store only.
I am new to SAPUI5 and I am very much in need of your help.
I have created an XML view and bound an OData model to it like below. Now all the controls in the view got bound and I am able to see the data.
this.getView().setModel(oModel);
Now I have a requirement in which I have to completely remove this binding from the view. I destroyed the oModel and removed all its bindings. And now when I refresh the view, the data still exists in the screen. I want all the data from the view to disappear.
oModel.destroy();
oModel.refresh();
this.getView().getModel().refresh(true);
I assume that you're using an sap.ui.model.odata.ODataModel to retrieve odata, then done binding using, for example, a JSON model, like so,
var oJson = new sap.ui.model.json.JSONModel({data : oData);
/* Here 'data' is any name that you provide to identify your data model,
'oData' is the data that is received as response from the sap.ui.model.odata.ODataModel */
And set this model to the view like you have mentioned,
this.getView().setModel();
Now, to remove this data from the view you can try the following,
oJson.setData({data : null}, true);
This would set the previously set oData to null and therefore all data binding from the controls in the view would be removed(changed to null).
I believe oJson.refresh() is optional, but you can try adding that as well if the change is not reflected.
Its an approach until may be you find something better :) Here is the documentation for the APIs that I've used.
If you are using
var dataModel = new sap.ui.model.json.JSONModel();
dataModel.setData(oDataResponse); //Data returned from oData.Read()
this.getView().setModel(dataModel, "dataModel");
Retrieve the model, Set the model to null, Update the binding
var dataModel = this.getView().getModel("dataModel");
if(dataModel){
dataModel.setData(null);
dataModel.updateBindings(true);
}