How to get notified when a section of sap.uxap.ObjectPageLayout changes in SAPUI5 1.38? - sapui5

I am working with a SAPUI5 version 1.38 and use in an application the control sap.uxap.ObjectPageSection within sap.uxap.ObjectPageLayout. At a certain section, when you click on it, an event should happen.
I haven't found a solution for this yet unfortunately. See:
I have already tried with attachBrowserEvent and addEventDelegate. But unfortunately, this does not work for this control.
Does anyone have any other ideas how to solve this problem? A workaround?
I would be very grateful for any help.
View1.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("test123.test123.controller.View1", {
onInit: function () {
},
onAfterRendering: function () {
var showMessage = function () {
sap.m.MessageToast.show("text");
return false;
};
this.byId("section2").attachBrowserEvent("click", showMessage);
this.byId("section2").addEventDelegate({
onclick: function () {
sap.m.MessageToast.show("text");
}
});
}
});
});
View1.view.xml
<mvc:View controllerName="test123.test123.controller.View1" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml"
displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:uxap="sap.uxap">
<App id="idAppControl">
<pages>
<Page title="{i18n>title}">
<content>
<uxap:ObjectPageLayout id="ObjectPageLayoutId"
useIconTabBar="true"
alwaysShowContentHeader="true">
<!-- SECTION 1 -->
<uxap:sections>
<uxap:ObjectPageSection titleUppercase="false" id="section1" title="Section 1">
<uxap:subSections>
<uxap:ObjectPageSubSection>
<uxap:blocks>
<Label text="Content 1" />
</uxap:blocks>
</uxap:ObjectPageSubSection>
</uxap:subSections>
</uxap:ObjectPageSection>
</uxap:sections>
<!-- SECTION 2 -->
<uxap:sections >
<uxap:ObjectPageSection titleUppercase="false" id="section2" title="Section 2">
<uxap:subSections>
<uxap:ObjectPageSubSection>
<uxap:blocks>
<Label text="Content 2" />
</uxap:blocks>
</uxap:ObjectPageSubSection>
</uxap:subSections>
</uxap:ObjectPageSection>
</uxap:sections>
</uxap:ObjectPageLayout>
</content>
</Page>
</pages>
</App>
</mvc:View>

Check out the documentation of 1.38. There is an event called tabSelect. The event is comparable to the event navigate in 1.40.[1]
You can use it as long as the property useIconTabBar equals true:
<uxap:ObjectPageLayout tabSelect=".onTabSelect" useIconTabBar="true">
[1] ⚠️ BREAKING CHANGE: with commit eb75945 (merged with the 1.40 release), the event tabSelect gets removed in favor of navigate! If the application runs with 1.40 or higher in the future, tabSelect should be renamed to navigate also in your code. But please review the differences between the two events beforehand.

Related

How to get $count into a tile

I am an ABAP developer who is just trying to take the first steps in SAPUI5/Fiori.
So my very simple task is to create a fiori app with a single tile to show the number of EDIDC records.
View1.controller.js:
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("QuickStartApplication.controller.View1", {
onGetValue: function ( ) {
var oTileValue = this.getView().byId("tile1");
this.getModel().read("/EDIDCSet/$count", {
success: $.proxy(function (oEvent, oResponse) {
// var count = Number(oResponse.body);
var count = "1337";
oTileValue.setValue(count);
}, this)
});
}
});
});
View1.view.xml:
<mvc:View xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
controllerName="QuickStartApplication.controller.View1">
<App id="idAppControl">
<pages>
<Page xmlns="sap.m" id="pageId" title="TileTest" floatingFooter="true">
<content>
<Button xmlns="sap.m" text="Button" id="button0" press=".onGetValue"/>
<GenericTile class="sapUiTinyMarginBegin sapUiTinyMarginTop tileLayout" header="Country-Specific Profit Margin" subheader="Expenses"
press="press" id="tile1">
<TileContent unit="EUR" footer="Current Quarter">
<NumericContent scale="M" value="1000" valueColor="Error" indicator="Up" withMargin="false"/>
</TileContent>
</GenericTile>
</content>
</Page>
</pages>
</App>
</mvc:View>
As you can see, I can't even pass the value "1337" that I hardcoded.
​My first mistake was to adress the tile and not the numeric content of the file. So first, I gave the ID to the numeric content:
​
<NumericContent scale="M" value="" valueColor="Error" indicator="Up" withMargin="false" id="num1"/>
​
​Then, I've adjusted the line, to access the object:
var oTileValue = this.getView().byId("num1");
​The last thing I learned was, that the model is connected to the view. So to access this, I changed the line to:
​this.getView().getModel().read("/EDIDCSet/$count", {
​Now I can call my function onGetValue and it's working.

Executing a function based on a click event on an html element in SAPUI5

Hi I'm trying to get a function defined in my controller to execute when I press on a specific area of a picture. I'm using an html map to define the areas of my picture (code below)
<mvc:View id="Main" controllerName="Demo.picture.controller.Main" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core">
<App id="idAppControl">
<pages>
<Page title="{i18n>title}">
<content>
<Image src = "Some image source" alt="Image" useMap="Map"/>
</content>
</Page>
</pages>
</App>
<html:map name="Map" id="Map">
<html:area id= "area_1" shape="rect" coords= "0,0,240,215" alt="Chart" onclick="???"/>
<html:area id = "area_2" shape="rect" coords="240,0,480,215" alt="Start" onclick="???"/>
</html:map> </mvc:View>
Not sure if using onclick is the right way of doing this.
Controller code:
sap.ui.define([
"sap/ui/core/mvc/Controller"], function (Controller) {
"use strict";
return Controller.extend("Demo.picture.controller.Main", {
SomeMethodFoo: function () {
"method to be executed when area_1 is pressed"
},
SomeMethodGoo: function () {
"method to be executed when area_2 is pressed"
}
});});
Is it possible to attach an eventHandler for a onclick event to these areas? Or is there some other way to do this?
I guess that it would be something like this:
onclick="sap.ui.getCore().byId('__xmlview0').getController().SomeMethodFoo()"
but your need to manage yourself to know your view ID, which won't be always '__xmlview0'

Flexible Column Layout Navigation (SAPUI5)

I've created an app with SAPUI5 that makes use of a Flexible Column Layout.
I'm trying to navigate between pages, but I'm having difficulty.
Here is the main xml view:
<mvc:View id="Main" controllerName="SAP.demo.controller.Main" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
displayBlock="true" xmlns="sap.f" xmlns:core="sap.ui.core" xmlns:m="sap.m">
<m:App id="idAppControl">
<m:pages>
<m:Page title="{i18n>title}">
<m:content>
<FlexibleColumnLayout id="fcl" initialMidColumnPage="start" layout="TwoColumnsBeginExpanded">
<beginColumnPages>
<m:Page title = "Master">
<m:content>
<Button text="Chart Button" press="displayChart"/>
</m:content>
</m:Page>
</beginColumnPages>
<midColumnPages>
<m:Page id="start" title = "Detail">
<m:content>
<core:Fragment fragmentName="SAP.demo.view.Start" type="XML"/>
</m:content>
</m:Page>
<m:Page id="charts" title="Charts">
<m:content>
<core:Fragment fragmentName="SAP.demo.view.Charts" type="XML"/>
</m:content>
</m:Page>
</midColumnPages>
</FlexibleColumnLayout>
</m:content>
</m:Page>
</m:pages>
</m:App>
I want to navigate from the start page to the charts page. The controller is as follows:
sap.ui.define([
"sap/ui/core/mvc/Controller"], function (Controller) {
"use strict";
return Controller.extend("SAP.demo.controller.Main", {
displayChart:function(oEvent){
this.byId("fcl").toMidColumnPage("charts");
}
});});
Can someone please advise as to what I'm doing wrong, because it stays on the start page even after I press the button.
This is because the real ID of the view is not "charts" but "__xmlview0--charts".
Be careful with the ID always and use the API method byId('theIDHere').
In your case use one of the following options:
displayChart:function(oEvent){
this.getView().byId("fcl").toMidColumnPage(this.getView().byId("charts"));
}
Or
displayChart:function(oEvent){
this.getView().byId("fcl").toMidColumnPage(this.getView().byId("charts").getId());
}
And also add the correct XML namespace to your button
<m:Button text="Chart Button" press="displayChart"/>
Managed to fix it with the following code:
displayChart: function () {
this.byId("fcl").toMidColumnPage(this.createId("charts"));
},

Page Is Blank Without Throwing Any Errors

I am trying to display few tiles in a tile container which fetches data from a dummy JSON file. I have coded exactly shown in this sample. But my page appears empty. Also it doesn't show any errors in the console. Below are the snippets of my code.
View1.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller) {
"use strict";
return Controller.extend("AdminMovie.controller.View1", {
});
});
View1.view.xml
<mvc:View
displayBlock="true"
controllerName="AdminMovie.controller.View1"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
>
<Page showHeader="false" enableScrolling="false">
<mvc:XMLView viewName="AdminMovie.view.TileContainer"/>
<footer>
<OverflowToolbar id="otbFooter">
<ToolbarSpacer/>
<Button type="Accept" text="Add New Movie"/>
</OverflowToolbar>
</footer>
</Page>
</mvc:View>
TileContailner.view.xml
<mvc:View
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="AdminMovie.controller.TileContainer"
>
<App>
<pages>
<Page
showHeader="false"
enableScrolling="false"
title="Stark"
>
<TileContainer id="container"
tileDelete="handleTileDelete"
tiles="{/MovieCollection}"
>
<HBox>
<StandardTile
icon="{icon}"
type="{type}"
number="{number}"
numberUnit="{numberUnit}"
title="{title}"
info="{info}"
infoState="{infoState}"
/>
</HBox>
</TileContainer>
<OverflowToolbar>
<Toolbar>
<ToolbarSpacer/>
<Button
text="Edit"
press=".handleEditPress"
/>
<ToolbarSpacer/>
</Toolbar>
</OverflowToolbar>
</Page>
</pages>
</App>
</mvc:View>
TileContainer.js
sap.ui.define([
"jquery.sap.global",
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel"
], function(jQuery, Controller, JSONModel) {
"use strict";
return Controller.extend("AdminMovie.controller.TileContainer", {
onInit: function(evt) {
// set mock model
var sPath = jQuery.sap.getModulePath("AdminMovie", "/MovieCollection.json");
var oModel = new JSONModel(sPath);
this.getView().setModel(oModel);
},
handleEditPress: function(evt) {
var oTileContainer = this.byId("container");
var newValue = !oTileContainer.getEditable();
oTileContainer.setEditable(newValue);
evt.getSource().setText(newValue ? "Done" : "Edit");
},
handleTileDelete: function(evt) {
var tile = evt.getParameter("tile");
evt.getSource().removeTile(tile);
}
});
});
Cause
The root view is missing a root control or the height of the parent HTML elements is not set to 100%. The child elements cannot be rendered in full size.
Resolution
For Standalone or Top-Level Applications
Add sap.m.App (or sap.m.SplitApp in case of a master-detail layout) once in the entire application project to your root view:
<!-- Root view (typically "App.view.xml") -->
<mvc:View controllerName="..."
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
displayBlock="true"
>
<App id="topLevelApp"> <!-- Not in any other views! -->
<pages>
<!-- ... -->
</pages>
</App>
</mvc:View>
Root controls such as sap.m.App, sap.m.SplitApp, and sap.m.Shell write:
a bunch of properties into the header of the HTML document e.g. the viewport meta tag via sap/ui/util/Mobile.init.
height: 100% to all its parent elements by default (unless isTopLevel is disabled). src
The reason why the linked sample is working, is that the control sap.m.App was already added in index.html. The samples shown in the Demo Kit, however, often miss index.html in the code page to be shown which can be confusing.
For Nested or Embedded Applications
If you're developing an app that is to be rendered within an an existing app, keep in mind that the top-level app might come already with one root control (sap.m.App with isTopLevel enabled or sap.m.SplitApp) in its root view. I.e. in this case:
Add height="100%" to the View node of the root view definition, and
Either use <App isTopLevel="false"> or replace the <App> with <NavContainer>.
<!-- Root view (typically "App.view.xml") -->
<mvc:View controllerName="..."
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
displayBlock="true"
height="100%"
> <!-- ↑ Set height="100%" -->
<App isTopLevel="false"> <!-- or:
<NavContainer> if the UI5 version is below 1.91 -->
<pages>
<!-- ... -->
</pages> <!--
</NavContainer> -->
</App>
</mvc:View>
Otherwise, not using the isTopLevel="false" will cause the footer area of the embedded app to be pushed out of the viewport. This is a common issue e.g. for the views that are intended to extend the standard SAP Fiori app "My Inbox" since the app already contains one root control as a top-level UI element. Refer to SAP KBA #3218822.
⚠️ For other readers: if you're not using a TileContainer, see my previous answer for general solutions → https://stackoverflow.com/a/50951902/5846045
Causes for empty TileContainer
Unexpected child control
Besides the missing root control, the <TileContainer> in your code contains a list of HBoxes.
<TileContainer>
<HBox> <!-- ❌ Wrong aggregation child! -->
<StandardTile />
The default aggregation of TileContainer is, however, a control that is derived from sap.m.Tile.
Hence, you should be getting the following error message in the browser console:
Uncaught Error: "Element sap.m.HBox#__hbox1" is not valid for aggregation "tiles" of Element sap.m.TileContainer#__xmlview1--container
Please, remove the <HBox> as the binding template:
<TileContainer>
<StandardTile /> <!-- ✔️ -->
TileContainer contains only one Tile
There was a bug (issue #1813) in the TileContainer which failed making the aggregation visible in Chrome (works in Firefox) if there was only a single Tile. The fix is delivered with OpenUI5 version 1.56+, 1.54.2+, 1.52.8+, 1.50.9+, 1.48.19+, and 1.46.2+.

Object Page with blocks

I've got this ObjectPageLayout:
request.view.xml
<ObjectPageLayout>
<headerTitle>
...
</headerTitle>
<headerContent>
...
</headerContent>
<sections>
<ObjectPageSection
mode="Collapsed">
<subSections>
<ObjectPageSubSection title="fooBlock">
<blocks>
<blockdetail:FormBlock columnLayout="auto" /> <!-- MY BLOCK -->
</blocks>
</ObjectPageSubSection>
</subSections>
</ObjectPageSection>
</sections>
</ObjectPageLayout>
FormBlockCollapsed.view.xml (MY BLOCK)
<mvc:View xmlns:f="sap.ui.layout.form" xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core" xmlns:l="sap.ui.layout" xmlns="sap.m"
controllerName="NAMESPACE.blocks.DetailsBlockCommon">
<FlexBox>
<HBox>
<VBox>
<f:SimpleForm >
<f:content>
<CheckBox class="sapUiSmallMarginBegin sapUiSmallMarginTop" id="myCheckbox" />
</f:content>
</f:SimpleForm>
</VBox>
</HBox>
</FlexBox>
...
</mvc:View>
So far, everything is fine. My Object page looks good a the checkbox is shown.
In my Controller request.controller.js i want to validate the checkbox in FormBlockCollapsed.view.xml
validateBlockForm: function(format){
console.log( oView.byId("myCheckbox").checked() ); //oView.byId("myCheckbox") is undefined
}
But i've no access to my checkbox in the block.
Cannot read property 'checked' of undefined
Further infos
FormBlock.js
sap.ui.define(['sap/uxap/BlockBase'], function (BlockBase) {
"use strict";
var MultiViewBlock = BlockBase.extend("NAMESPACE.blocks.FormBlock", {
metadata: {
views: {
Collapsed: {
viewName: "NAMESPACE.blocks.FormBlockCollapsed",
type: "XML"
}
}
}
});
return MultiViewBlock;
}, true);
DetailBlockCommon.js
sap.ui.define([
"NAMESPACE/controller/BaseController"
], function (BaseController) {
"use strict";
return BaseController.extend("NAMESPACE.blocks.DetailsBlockCommon", {
});
});
You can access the elements in a section by having the block's id and element's id.
First we have to define an id for the block in the xml view:
<blocks>
<blockdetail:FormBlock id="formBlock" columnLayout="auto" /> <!-- MY BLOCK -->
</blocks>
Then we generate the id of the elements like the following in the view controller. The state of the art here is to add -Collapsed-- as part of the id that adds by SAPUI5 to sections elements.
var sFieldId = this.getView().createId("formBlock") +
"-Collapsed--myCheckbox";
var oCheckbox = sap.ui.getCore().byId(sFieldId);
Check if oView is defined.
you can easily get it by this.getView()