FlexibleColumnLayout on second view not working SAP UI5 - sapui5

I am building a view with hardcoded data. which comes from home screen to the next view which is supposed to be a split view screen.
I am using FlexibleColumnLayout and inside of it begin and end layout to call views from my view folder. I have been following this tutorial. and even then my split view is not expanding on click.
My aggregation looks like this (I am not sure if it is correct):
App -> (View1, FCLView)
FCLView -> (MasterVIew, DetailView)
FCLView:
<mvc:View displayBlock="true" height="100%" xmlns="sap.f" xmlns:mvc="sap.ui.core.mvc">
<FlexibleColumnLayout id="flexibleColumnLayout" backgroundDesign="Solid">
<beginColumnPages>
<mvc:XMLView id="beginView" viewName="Ui5.Ui.view.MasterView"/>
</beginColumnPages>
<midColumnPages>
<mvc:XMLView id="detailView" viewName="Ui5.Ui.view.DetailView"/>
</midColumnPages>
</FlexibleColumnLayout>
</mvc:View>
component.js
...
getHelper: function () {
var oFCL = this.getRootControl().byId('flexibleColumnLayout'),
oSettings = {
defaultTwoColumnLayoutType: sap.f.LayoutType.TwoColumnsMidExpanded,
initialColumnsCount: 2
};
return FlexibleColumnLayoutSemanticHelper.getInstanceFor(oFCL, oSettings);
}
MasterViewController
...
onListItemPress: function (oEvent) {
MessageToast.show("here");
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var oFCL = this.oView.getParent().getParent();
oFCL.setLayout(fioriLibrary.LayoutType.TwoColumnsMidExpanded);
}
I am following this tutorial
The scenario is, I have my first fullscreen view (View1) in which there's a button and it will navigate to second view which is a split view. (table and on clicking a row, the detail view will expand).
I am new to SAP, any kind of help would be appreciated.

It is difficult to debug your code excerpts, because there are several other things that can go wrong. (e.g. did you configure the use the sap.f.router instead of the sap.m.router in the manifest?)
The easiest way to start with a FlexibleColumnLayout is to begin with the UI5 MasterDetail-Template
This can be downloaded from Github or easily created in the WebIDE with a few clicks (new Project from template -> select Master Detail Application)
You can read more about the Template in the Demokit

Related

SAP Fiori: Back button in fragments

I am working on a SAP Fiori app and I am stuck in this problem for about 2 weeks with no result. I have a "create" fragment which is attached to "Detail" view.
When I open the "create" fragment and want to go back to the main detail view, the back button doesn't work therefore I have to refresh the app.
I guess the back button doesn't work the same way between views & between fragments.
Here's my back button function :
cancel: function() {
var oHistory = sap.ui.core.routing.History.getInstance(),
sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
// The history contains a previous entry
history.go(-1);
}
},
Here when I display sPreviousHash, it's undefined. Why?
Where is the back button that you are referring to?
I would expect that the fragment is a dialog and therefore that there is no back button. A close button is needed which will result in the fragment being closed. Depending on the requirements, the back navigation could then be done from the controller where the fragment was created.
Fragments are a technique to reuse UI parts, but are not part of the MVC concept. You cannot navigate directly to/from a fragement and this has to be done using views. Therefore the history is not available in a fragment. The BROWSER back button will take you to the previous screen in the BROWSER history.
Controller of the view in which the fragment as a dialog is opened.
_initializeReviewDialog: function() { this._oReviewDialog = sap.ui.xmlfragment(this.getView().getId(), "ReviewDialog", this);
this.attachControl(this._oReviewDialog);
},
Event in View that triggers the dialog opening
onEditReviewPressed: function(oEvent) {
if (!this._oReviewDialog) {
this._initializeReviewDialog(); }
}
this._oReviewDialog.open();
},
onReviewDialogOKPressed: function(oEvent) {
this._oReviewDialog.close();
},
Add fragment as a Dependent, so that models and events from owning view/controller are know
attachControl: function(oControl) {
var sCompactCozyClass = this.getOwnerComponent().getContentDensityClass();
jQuery.sap.syncStyleClass(sCompactCozyClass, this.getView(), oControl);
this.getView().addDependent(oControl);
},
FragmentDefinition
<core:FragmentDefinition id="ReviewDialogFragment" xmlns="sap.m" xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core">
<Dialog id="reviewDialog" >
<content>
... </content>
<beginButton>
<Button id="btnOK" text="{i18n>xbut.ok}" press="onReviewDialogOKPressed"/>
</beginButton> </Dialog>
</core:FragmentDefinition>

How to start XML preprocessor without return a view component

I'm trying to create a launchpad for a set of applications that we use here. One of my problems is that I need to add different tiles in a tile container (slide,custom,standard, etc) and what I think that may be a solution is use XML templating to do that. What I want to achieve is something like that:
<TileContainer id="tileList"
allowAdd="true"
tileDelete="onDelete"
tiles="{path:'Atalhos>/' ,sorter:{path:'Atalhos>TileText',group:false}}">
<template:if test="{path:'Atalhos>TileCode', operator:'EQ',value1:'teste1'}">
<template:then>
<core:Fragment fragmentName="pelissari.soficom.launchpad.view.StandardTile" type="XML"/>
</template:then>
<template:else>
<core:Fragment fragmentName="pelissari.soficom.launchpad.view.StandardTile" type="XML"/>
</template:else>
</template:if>
</TileContainer>
but the problem is that I'm having this error when I try to do that.
UIComponent-dbg.js:52 Uncaught Error: failed to load
'http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js'
from
resources/http://schemas/sap/com/sapui5/extension/sap/ui/core/template/1/if.js:
404 - Not found
I know that I need to start the preprocessor to use preprocessing instructions but all the examples that I found makes me more confuse that I was before.
My project is based on the sapui5 tutorial "WalkThrough where I have a component that starts an app view configured in the manifest and this view is navigate to the launchpad view by routing configuration again in the mainfest. all the examples create a view in the component CreateComponent function or in some controller function that loads other view. I just need to start the preprocessor for the list of tiles that I load from the entity set "/TileSet".
I found another way to do what I want. Now I'm using factory function to create the tiles as I need.
tileFactory: function(sId, oContext) {
var atalho = oContext.getProperty(oContext.sPath)
var oUIControl = null;
if (atalho.TileCode == 'teste2') {
oUIControl = new sap.m.StandardTile(sId, {
title: atalho.TileText
});
oUIControl.addStyleClass('tileSize3');
} else {
oUIControl = new sap.m.StandardTile(sId, {
title: atalho.TileText
});
oUIControl.addStyleClass('tileSize1');
}
oUIControl.attachPress(this.onPress, this);
oUIControl.addStyleClass('tile');
return oUIControl;
}
<Page id="tileGroup" showHeader="true"
content="{path:'Atalhos>/' ,sorter:{path:'Atalhos>TileOrder',group:false},factory:'.tileFactory'}">

How to get element's id of another view SAPUI5

I have 3 views say first,second & third. I need to access a vertical layout's id of second view from first view. For which I have used sap.ui.getCore().byId("__xmlview1--spend_layt"); to retrieve it. It works but when I navigate to third view & come back, id changes to __xmlview28--spend_layt & the control not works. How to fix this?
EDIT :
First.view.xml
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="budgetspend.controller.First" xmlns:html="http://www.w3.org/1999/xhtml"
displayBlock="true">
<App id="BA_APP">
<pages>
<HBox width="100%" height="100%" id="header_container">
<items>
<Image class="logo" src="../images/logo_new.png"/>
<Image class="header" src="../images/header-bg.png"/>
<html:ul class="tab">
<html:li>
<html:a id="onBud" class="tablinks active">Tab 1
</html:li>
<html:li>
<html:a id="onSpend" class="tablinks">Tab 2</html:a>
</html:li>
</html:ul>
<mvc:XMLView viewName="budgetspend.view.second"/>
</items>
</HBox>
</pages>
</App>
</mvc:View>
In the second view, I use 2 vertical layouts. one for tab 1 & another for tab 2. Only one visible at a time. Tab click events are written in First.controller.js. I don't know how to access ID's of vertical layouts(in second view) from First.
I am just exploring how standard html will work on SAPUI5 as I am aware of using sap.m.IconTab.
What you are facing is due to the dynamic creation of elements. Every time you leave a screen and goes back into it, the items are regenerated, but they can't have the same ID, since they were used before.
One solution to this is to create a Utils folder, and create an object, let's say UIHelper.
This file would look like this:
jQuery.sap.declare('my.app.Utils.UIHelper');
my.app.Utils.UIHelper = {
controllerInstance1 : null,
controllerInstance2 : null,
controllerInstance3 : null,
//Add "getters and setters" for each of these attributes (repeat for Controller 2 & 3)
setControllerInstance1 : function(oController){
this.controllerInstance1 = oController;
},
getControllerInstance1 : function(){
return this.controllerInstance1;
}
};
Now, at the controller file for each of your views, you add the following line at the top of the file:
jQuery.sap.require('my.app.Utils.UIHelper');
And on the onInit event of those controllers, you set the controller instance on the UIHelper object:
my.app.Utils.UIHelper.setControllerInstance1(this);
And when you want to get the different views from anywhere in the code, assuming that the views are assigned to one of the controllers, you can just use the following:
my.app.Utils.UIHelper.getControllerInstance1().getView();
Update in my answer after the update on the question:
To access the layout from the second view, you could do the following:
var layout = my.app.Utils.UIHelper.getControllerInstanceView2().byId('spend_layt');

Link to route without additional JS code

I'm a beginner to OpenUI5 and have written a menu like below:
view:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" select="goToRoute"></NavigationListItem>
</NavigationList>
controller:
goToRoute: function() {
this.getRouter().navTo("peoplelist");
}
That works, but it's bad, as I have a couple of menu items and JS events for each of them.
I wish I had something like this below, without any JS behind, but couldn't find anything in documentation and examples.
view:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" linkToRoute="peoplelist"></NavigationListItem>
</NavigationList>
Anyone knows?
You can build a generic event handler which derives the target route from the corresponding item. To achieve this you can make use of custom data which you can add to controls in a declarative way. For this add the following line to your opening View tag:
xmlns:custom="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
Adopt your navigation list:
<NavigationList id="navigationList" width="12rem">
<NavigationListItem text="People" icon="sap-icon://card" select="onItemSelect" custom:route="peopleList"/>
</NavigationList>
And your controller:
onItemSelect : function(event) {
var item = event.getSource();
var route = item.data("route");
this.getRouter().navTo(route);
}
Here you find further details.

Identifying component rootview viewname

Imagine a component with a root view like so:
rootView: 'myapp.view.App'
The app view looks like this:
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
xmlns="sap.m"
controllerName="myapp.controller.App"
displayBlock="true">
<App id="myapp">
<mvc:XMLView id="page1" viewName="myapp.view.Page1" />
</App>
</mvc:View>
As you can see there is a controller set up for this view. The view myapp.view.Page1 is another XML view, has a controller of its own and contains a sap.m.Page control.
This Page1 controller cannot access any controls without specifying __xmlview0-- in front of the Id. I know it's in a view, because the App is in a view. createId will create something relative to the current controller, so it will return __xmlview0--page1.
For instance, I can get the app from my myapp.controller.Page, but I have to access using the view name too. The same goes for my pages. Navigating to a new page in the app looks like this:
var app = this.byId('__xmlview0--myapp');
app.to('__xmlview0--page1');
this.createId('myapp') will give me __xmlview0--page1--myapp.
I also tried getting the component itself out this.getOwnerComponent() and use the createId and getId methods, but this leaves me with __component0 instead of __xmlview0, so that's a no-go too.
edit
Not a super clear story. Maybe this will go you some visuals:
-Component.js
- App.view.xml <App id="myapp"></App>
- Page1.view.xml <Page id="page1"></Page>
- App.controller.js
- Page1.controller.js
//byId uses createId.
//myapp has id __xmlview0--myapp
this.createId('myapp') = __xmlview0--page1--myapp
this.getView().createId('myapp') = __xmlview0--page1--myapp
this.getOwnerComponent().byId('myapp') = __component0--myapp
this.getOwnerComponent().getView() is not a function
How do I determine through my controllers to add __xmlview0? Which createId method do I use? Is my rootView wrong and is there a more efficient way? How do I get myapp out of the component?
Since you are using the component and you have rootview mentioned in the component configuration there is an API to retrieve the root view
var comp = this.getOwnerComponent().getMetadata() // this is the view i am referring to here.
comp.getRootView()
You could write a recursively navigate this.parent() until you have the sViewName equal to the comp.getRootView(). This entry gets the rootview you are looking for and then sId gets you the ID which you can use to append.
I am not sure what you are trying to achieve but this is a hack i thought you can use to derive the rootview's ID.
Alternatively you can also specify the rootView ID while defining component something like this
rootView: {
viewName : "ui.sample.demo.view.App",
id : "Root",
type : "XML"
},