setBusy not executing - sapui5

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();
},

Related

The flexible column layout arrow does not work properly

I have created a flexible column layout and unfortunately it does not work properly.
When I want to expand the left part, I have to click on arrow twice instead once:
I am trying to figure out, but unfortunately could not find the error.
The view of Flexible Column Layout:
<mvc:View xmlns="sap.f" xmlns:mvc="sap.ui.core.mvc" xmlns:m="sap.m" displayBlock="true" controllerName="io.example.fclpoc.controller.App"
height="100%">
<FlexibleColumnLayout id="fcl" stateChange="onStateChanged" layout="{/layout}" backgroundDesign="Solid"></FlexibleColumnLayout>
</mvc:View>
and the controller:
sap.ui.define([
"sap/ui/model/json/JSONModel",
"sap/ui/core/ResizeHandler",
"sap/ui/core/mvc/Controller",
"sap/f/FlexibleColumnLayout"
], function (JSONModel, ResizeHandler, Controller, FlexibleColumnLayout) {
"use strict";
return Controller.extend("io.example.fclpoc.controller.App", {
onInit: function () {
this.oRouter = this.getOwnerComponent().getRouter();
this.oRouter.attachRouteMatched(this.onRouteMatched, this);
this.oRouter.attachBeforeRouteMatched(this.onBeforeRouteMatched, this);
},
onBeforeRouteMatched: function (oEvent) {
var oModel = this.getOwnerComponent().getModel();
var sLayout = oEvent.getParameters().arguments.layout;
// If there is no layout parameter, query for the default level 0 layout (normally OneColumn)
if (!sLayout) {
var oNextUIState = this.getOwnerComponent().getHelper().getNextUIState(0);
sLayout = oNextUIState.layout;
}
// Update the layout of the FlexibleColumnLayout
if (sLayout) {
oModel.setProperty("/layout", sLayout);
}
},
_updateLayout: function (sLayout) {
var oModel = this.getOwnerComponent().getModel();
// If there is no layout parameter, query for the default level 0 layout (normally OneColumn)
if (!sLayout) {
var oNextUIState = this.getOwnerComponent().getHelper().getNextUIState(0);
sLayout = oNextUIState.layout;
}
// Update the layout of the FlexibleColumnLayout
if (sLayout) {
oModel.setProperty("/layout", sLayout);
}
},
onRouteMatched: function (oEvent) {
var sRouteName = oEvent.getParameter("name"),
oArguments = oEvent.getParameter("arguments");
this._updateUIElements();
// Save the current route name
this.currentRouteName = sRouteName;
},
onStateChanged: function (oEvent) {
var bIsNavigationArrow = oEvent.getParameter("isNavigationArrow"),
sLayout = oEvent.getParameter("layout");
this._updateUIElements();
// Replace the URL with the new layout if a navigation arrow was used
if (bIsNavigationArrow) {
this.oRouter.navTo(this.currentRouteName, {
layout: sLayout
}, true);
}
},
// Update the close/fullscreen buttons visibility
_updateUIElements: function () {
var oModel = this.getOwnerComponent().getModel();
var oUIState = this.getOwnerComponent().getHelper().getCurrentUIState();
oModel.setData(oUIState);
},
onExit: function () {
this.oRouter.detachRouteMatched(this.onRouteMatched, this);
this.oRouter.detachBeforeRouteMatched(this.onBeforeRouteMatched, this);
}
});
});
I looked also in the debug console:
However no errors occur. I have also compare my code with https://sapui5.hana.ondemand.com/#/entity/sap.f.FlexibleColumnLayout/sample/sap.f.sample.FlexibleColumnLayoutWithTwoColumnStart/code/webapp/controller/FlexibleColumnLayout.controller.js and could not find differences.
What am I doing wrong?
The app can be found here https://github.com/softshipper/fclpoc
Update
I have run the app in my edge browser and it does not have any extension installed. The behavior is the same.
Here is the console output of edge:
This is less a direct answer to the question "why does my app do that". It's more of a help to self-help.
Basically, if you put a break point in each of the methods in your App controller, you will see that the layout is moving in the correct position first, then it is moving back in the incorrect position (it happens so fast that you dont see without debugger).
The layout is being set several times in the whole process. sometimes changing nothing, sometimes not. In the end, one of your methods sets the wrong layout.
PS: you have a semantic error, not a syntactic one (the app does what you asked it to do), so there are no errors in the console.

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.

How to get the data of a view

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.

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.

How to access old and new values before submitting with jeditable

I have a field being updated by jeditable. I want to output a warning message before submitting updates if the value is being reduced (which would result in data being lost), but not if it's being increased.
This seems a good candidate for jeditable's onsubmit function, which I can trigger happily. I can get the new value from $('input', this).val(), but how do I get the original value to which to compare it in this context?
...
Since posting the above explanation / question, I've come up with a solution of sorts. By changing the invokation in jquery.ready from
$('#foo').editable(...);
to
$('#foo').hover(function(){
var old_value = $(this).text();
$(this).editable('ajax.php', {
submitdata {'old_value':old_value}
});
});
I can use settings.submitdata.old_value in the onsubmit method.
But there surely has to be a better way? jeditable must still have the old value tucked away somewhere in order to be able to revert it. So the question becomes how can I access that from the onsubmit function?
Many thanks in advance for any suggestions.
A much easier solution would be to add this line to your submitdata variable
"submitdata": function (value, settings) {
return {
"origValue": this.revert
};
}
Here is my editable (it is using the submitEdit function):
$(function () {
$('.editable').editable(submitEdit, {
indicator: '<img src="content/images/busy.gif">',
tooltip: '#Html.Resource("Strings,edit")',
cancel: '#Html.Resource("Strings,cancel")',
submit: '#Html.Resource("Strings,ok")',
event: 'edit'
});
/* Find and trigger "edit" event on correct Jeditable instance. */
$(".edit_trigger").bind("click", function () {
$(this).parent().prev().trigger("edit");
});
});
In submitEdit origvalue is the original value before the edit
function submitEdit(value, settings) {
var edits = new Object();
var origvalue = this.revert;
var textbox = this;
var result = value;
// sb experiment
var form = $(this).parents('form:first');
// end experiment
edits["field"] = form.find('input[name="field"]').val();
edits["value"] = value;
var returned = $.ajax({
url: '#Url.Action("AjaxUpdate")',
type: "POST",
data: edits,
dataType: "json",
complete: function (xhr, textStatus) {
// sever returned error?
// ajax failed?
if (textStatus != "success") {
$(textbox).html(origvalue);
alert('Request failed');
return;
}
var obj = jQuery.parseJSON(xhr.responseText);
if (obj != null && obj.responseText != null) {
alert(obj.responseText);
$(textbox).html(origvalue);
}
}
});
return (result);
}