01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | onInit: function () { this ._oModel = this .getOwnerComponent().getModel(); }, onButtonPress: function (oEvent) { //get Data var sPath = oEvent.getSource().getBindingContext().sPath; var oData = this .getView().getModel().getObject(sPath); var that = this ; //busy on this ._busyDialog = new sap.m.BusyDialog({}); this ._busyDialog.open(); //create this ._oModel.create( "/DataSet" , oData, { success: function (oData) { that._busyDialog.close(); sap.m.MessageToast.show(that.getResourceBundle().getText( "ok" )); }, error: function (oError) { that._busyDialog.close(); sap.m.MessageToast.show(that.getResourceBundle().getText( "nok" )); } }); }, |
Category: Fiori / SAPUI5
[SAPUI5] MyInbox: Integration of Detail View – EmbedIntoDetail
https://launchpad.support.sap.com/#/notes/2305401 (App to App Navigation CookBook.pdf)
https://blogs.sap.com/2020/07/31/fiori-my-inbox-integration-of-custom-detail-page/
Target:
Go to /n/ui2/fpld_cust and define a second target for your App, i.e. approve.

The approve target needs the “emdedIntoDetails” parameter:

SWFVISU:
Add the new target for your WF Task. Here you have access to all attributes of your Workitem-Container. Pass all your mandatory fields you’ve defined in your oData Entity.
Some examples: https://blogs.sap.com/2016/05/31/my-inbox-open-task-swfvisu-configuration/

If your missing some parameters, just add them in your Workitem Task and pass the values directly into it right from your Workflow Container. This looks much better.

Manifest:
Add a route to navigate via Inbox. The pattern has to match your inbox url.

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | "routes" : [ { "pattern" : "" , "name" : "master" , "target" : "master" }, { "pattern" : "DataSet/{Pernr},{Datum},{Infty}" , "name" : "object" , "target" : [ "master" , "object" ] }, { "pattern" : "detail/LOCAL_INBOX/{wfInstanceId}/{taskPath}" , "name" : "wfobject" , "target" : "object" } |
Detail.Controller:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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 }); this .getRouter().getRoute( "object" ).attachPatternMatched( this ._onObjectMatched, this ); //My Inbox Integration this .getRouter().getRoute( "wfobject" ).attachPatternMatched( this ._onWFObjectMatched, this ); this .setModel(oViewModel, "detailView" ); this .getOwnerComponent().getModel().metadataLoaded().then( this ._onMetadataLoaded.bind( this )); }, _onWFObjectMatched: function (oEvent) { this .getModel( "appView" ).setProperty( "/layout" , "MidColumnFullScreen" ); var compData = this .getOwnerComponent().getComponentData(); if (compData && compData.startupParameters && compData.startupParameters.PERNR && Array.isArray(compData.startupParameters.PERNR) && compData.startupParameters.PERNR[0]) { var sPernr = compData.startupParameters.PERNR[0]; var sDatum = compData.startupParameters.DATUM[0]; var sInfty = compData.startupParameters.INFTY[0]; this .byId( "detailPage" ).addStyleClass( "myInboxPage" ); this .getModel().metadataLoaded().then( function () { var sObjectPath = this .getModel().createKey( "/DataSet" , { Pernr: sPernr, Datum: sDatum, Infty: sInfty }); this ._bindView(sObjectPath); }.bind( this )); } }, |
[SAPUI5] uncheck checkbox if another one is selected
XML
1 2 | < Checkbox id = "Checkbox1" selected="{ path:'oModel>CB1' }" select="handleOrderSelected"></ Checkbox > < Checkbox id = "Checkbox2" selected="{ path:'oModel>CB2' }" select="handleRejectSelected"></ Checkbox > |
controller.js
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 | handleOrderSelected: function (oEvent) { //Wenn Checkbox1 selektiert, setze Checkbox2 auf false. var bSelected = oEvent.getParameter( "selected" ); if (bSelected) { var bindingContext = oEvent.getSource().getBindingContext( "oModel" ); this .oModelTemplate.setProperty( "CB2" , "" , bindingContext, false ); } }, handleRejectSelected: function (oEvent) { //Wenn Checkbox2 selektiert, setze Checkbox1 auf false. var bSelected = oEvent.getParameter( "selected" ); if (bSelected) { var bindingContext = oEvent.getSource().getBindingContext( "oModel" ); this .oModelTemplate.setProperty( "CB1" , "" , bindingContext, false ); } } |
[SAPUI5] Copy Table Row
Button für das Kopieren einer Zeile hinzufügen.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | < Table id = "itemsTable" items="{oModel>/ITEMS}"> < columns > < Column id = "splitColumn" hAlign = "Center" demandPopin = "false" > < Text text="{i18n>SPLIT}"/> </ Column > </ columns > < items > < ColumnListItem > < cells > < Button press = "onSplitPressed" id = "SPLIT_ROW" icon="{= ${oModel>CUSTOM_ITEM} === true ? 'sap-icon://delete' : 'sap-icon://add'}"/> </ cells > </ ColumnListItem > </ items > </ Table > |
Nur neu hinzugefügte Zeilen sollen auch wieder gelöscht werden dürfen, daher werden manuell hinzugefügte Zeilen markiert mit CUSTOM_ITEM = True;
Via Expression Binding wird dann das erforderliche Icon bestimmt.

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | onSplitPressed: function (oEvent) { var oContext = oEvent.getSource().getBindingContext( "oModel" ); var path = oContext.getPath(); var oModel = oContext.getModel(); var oItems = oModel.getProperty( "/ITEMS" ); var index = path.substr(path.length - 1); //selektiertes Item lesen var oItem = oModel.getProperty(path); //was soll passieren? Zeile hinzufügen oder entfernen? if (oItem.CUSTOM_ITEM !== true ) { //Neues Item anlegen var oNewItem = JSON.parse(JSON.stringify(oItem)); //Markiere neue Zeile, da nur diese auch wieder gelöscht werden darf oNewItem.CUSTOM_ITEM = true ; // +1 weil Zeile soll ja nach der Aktuellen einfügt werden index++; oItems.splice(index, 0, oNewItem); } else { // Item löschen oItems.splice(index, 1); } oModel.setProperty( "/ITEMS" , oItems); }, |
[Fiori] Debug deployed Fiori App
When opening the Dev-Tools for a deployed Fiori App, it will look like this:

You won’t see any controller.js to debug.
What to do? Close the Debugger-Tools and hit CTRL+ALT+SHIFT+P to open the Technical Information Dialog

Check the Checkbox (or choose a specific controller) and reload the app.


It reloads with a new URL parameter and if you open the Dev-Tools, you will now see the controller.js.

Other options to debug or at least to collect some information about your app are the UI5 Diagnostics (hit CTRL+ALT+SHIFT+S) and the UI5 Inspector which is a Brower Addon.
[SAPUI5] Formatting numbers
https://experience.sap.com/fiori-design-web/formatting-numbers/#usage
https://sapui5.netweaver.ondemand.com/sdk/#/topic/91f3145e6f4d1014b6dd926db0e91070
a few examples: https://github.com/brooklynb7/HTML5/blob/master/sapui5-dist-static/test-resources/sap/ca/ui/demokit/explored/views/type/number.view.xml
1 2 3 4 | < ObjectListItem title="{income>Month}" number="{ model : 'income', path : 'Cost', type: 'sap.ui.model.type.Integer', formatOptions: {groupingEnabled: true} }" numberUnit="EUR" /> |
[SAPUI5] Deploying the ui5 sample app on debian
I’m deploying the openui5-sample-app to a Linux Container running Debian Buster. First update the packages and install Node.js.
1 2 3 4 5 | apt update && apt upgrade -y apt install curl -y curl -sL https: //deb .nodesource.com /setup_12 .x | bash - apt install nodejs -y nodejs --version |
Install PM2 (process manager to manage Node.js applications) and the UI5 Tooling
1 2 | npm install pm2 -g npm install --global @ui5 /cli |
Now clone the openui5-sample-app and build it
1 2 3 4 5 | apt install git git clone https: //github .com /SAP/openui5-sample-app .git cd openui5-sample-app/ ui5 build -a cd .. |
Run your project on port 8000. With “startup” it will automatically create a systemd script.
1 2 3 4 5 | pm2 serve openui5-sample-app /dist/ 8000 pm2 startup pm2 save systemctl start pm2-root systemctl status pm2-root |
[SAPUI5] local ui5 development
1. Install node.js
2. Install UI5 Tooling
1 | npm install --global @ui5/cli |
3. Install Easy UI5 Generator, create a project and run it on your localhost
1 2 3 4 | npm install -g yo generator-easy-ui5 yo easy-ui5 cd <your project name> npm start |
4. Set up a Github project and do your initial push
1 2 3 4 | git add . git commit -m "Initial commit" git remote add origin https://github.com/user/myUI5App.git git push origin master |
5. Install your favorite Editor, e.g. Visual Studio Code or Atom, and open your project to edit it