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"));
},
Related
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.
I want to bind text from my JSON-Model to the text of a button.
My controller initializes my model:
onInit: function () {
var oModel = new JSONModel({
"test": "Hello"
});
this.getView().setModel(oModel, "jsonFile");
}
My View looks like this:
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" controllerName="sap.ui.demo.nav.controller.Home">
<Page id="_IDEGen_page0" title="{i18n>homePageTitle}" class="sapUiResponsiveContentPadding">
<content>
<Button id="_IDEGen_button0" text="Start new Game" press="onPressStartGame"/>
<Button text="{jsonFile>test}"/>
</content>
</Page>
</mvc:View>
But when I run my application, the ui5-inspector show my that the binding is active, but the text is not shown.
I have no idea, what the problem could be in this case. Who can help me? What could be the problem, that the text is not shown?
You forgot the slash in your binding
<Button text="{jsonFile>/test}"/>
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'
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+.
I need to retrieve id of a control (VBox which has id="multipleChoiceQuestion") and need to hide it on button press.
How to do this?
App.view.xml
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form" xmlns:core="sap.ui.core"
displayBlock="true" controllerName="opensap.onlinequestionnaire.controller.App" height="100%">
<VBox id="multipleChoiceHolder">
<HBox width="700px" backgroundDesign="Solid" alignItems="Center" id="mCHorHolder1">
<CheckBox id="checkBox1"/><Label text="{questionnaire>/data/0/answers/0}" id="multipleChoice1"/>
</HBox>
</VBox>
App.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller){
Controller.extend("opensap.onlinequestionnaire.controller.App", {
goToNext:function() {
alert("Next Question");
alert(this.byId('multipleChoiceQuestion'));
}
});
});
In my goToNext:function() I would like to retrieve the id of the VBox and would like to hide it.
I tried alerting this.byId() but it returns undefined.
Get the VBox:
// id as stated in the description
oVBox = this.getView().byId("multipleChoiceQuestion");
// or
// id as stated in the view in the code sample
oVBox = this.getView().byId("multipleChoiceHolder");
Set visibility:
oVBox.setVisible(false);
By the way, the id's of your post description and the view in your post's code sample are not identical. But I'm sure you're aware of this minor mix-up which has nothing to do with your question of a general approach to retrieve and hide a control. Just wanted to mention it to be on the safe side
The ID of your VBox is "multipleChoiceHolder" and not "multipleChoiceQuestion". So, shouldn't it be this.byId('multipleChoiceHolder') instead of this.byId('multipleChoiceQuestion')?