How to read all the tiles in the Tile Container SAP UI5 - sapui5

<core:FragmentDefinition xmlns="sap.m"xmlns:f="sap.ui.layout.form" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout">
<Page id="tileInfo" showHeader="false" enableScrolling="true" >
<TileContainer
id="getTiles"
tiles="{myModel1>TILECOLLECTION}">
<StandardTile
icon="{myModel1>icon}"
number="{myModel1>number}"
info="{myModel1>info}"
infoState="{myModel1>infostate}"
title="{myModel1>title}"
numberUnit="{myModel1>numberunit}"
press="handleTilePress"
class="myGreen"
/>
</TileContainer>
</Page>
</core:FragmentDefinition>
I want to read each tile in the TileContainer in the view controller. Is it possible ?

in the controller:
...
var oTileContainer = this.byId("getTiles");
var aTiles = oTileContainer.getTiles();
...
in the array aTiles are the tiles of the tiles aggregation of the tile container.

Use nested views instead of fragment.
code with nested views
Then you can get the tiles and apply logic below.
var oTileContainer = this.byId("myView--getTiles");
var aTilesLength = oTileContainer.getTiles().length;
for(var i = 0 ;i<aTilesLength;i++){
if(i%2 == 1){
oTileContainer.getTiles()[i].addStyleClass("blue");
}else{
oTileContainer.getTiles()[i].addStyleClass("green");
}
}

I have added a few more information. If we are not going byId we can use the below code to get the fragment details :
Thanks All.
Note : The code does not work in onInit function but works in other functions
var fragmentId = this.getView().createId("myFragment");
var tileContainer = sap.ui.core.Fragment.byId(fragmentId,"getTiles");
var oTiles = tileContainer.getTiles();

Related

SAP UI5 Dynamically switch between fragments

How do I dynamically switch between two fragments using click / press event?
I have the following XML fragment which in turn has nested two fragments:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core">
<IconTabFilter
id="containerFrag"
text="{name}"
key="{id}">
<dependents>
<core:Fragment
fragmentName="com.example.fragments.fragment1"
type="XML" />
<core:Fragment
fragmentName="com.example.fragments.fragment2"
type="XML" />
</dependents>
</IconTabFilter>
</core:FragmentDefinition>
Assuming each fragment has a button who's handler has the following
buttonPress: function(oEvent) {
let oView = this.getView();
let showFrag1 = oEvent.getParameter("arguments"); //showFrag1 = true / false
let fragToShow = showFrag1 ? oView.byId("frag1Id").clone() : oView.byId("frag2Id").clone()
let container = oView.byId("containerFrag");
container.destroyContent();
container.addContent(fragToShow);
}
When I debug using chrome, fragToShow updates with the correct frag depending on the showFrag1 argument, but the view doesn't get updated - container.addContent(fragToShow) seems to have no effect except if I reload the page
Not sure why this works but I had to go one up from the container and insert the new fragment there like so:
let container = oView.byId("containerFrag");
container.getParent().destroyContent();
container.getParent().addContent(fragToShow);
This example also helped: https://ui5.sap.com/#/entity/sap.ui.layout.form.Form/sample/sap.ui.layout.sample.Form354 - though they use removeAllContent and insertContent, both seem to work just fine.
Thanks #D. Seah and #Ethan Jewett

Navigate to same Detail View with Animation in SplitApp

I'm using a Split App which has
Master list
3 Detail Pages
MAster List shows a list of items ( here for example, bikes and cars list)
These are 3 detail pages:
Message page: for not found/welcome page when nothing is clicked on master list.
BikeProperties Page: which shows details if Bike is clicked.
CarProperties Page: which shows if Car is clicked.
Now, the issue is when I click on Car Product, there is an animation shown which navigates from say welcome page to car page.
However, if I click again a car product, binding is updated with no animation.
Similarly, if I select a Bike at this point ( after selecting car), the navigation happens with animation.
So, to summarize,
No animation is shown if same page is shown again in detail page.
Animation is shown when different detail page is loaded.
However, what I want is , irrespective of which detail page is currently shown, the navigation should happen again with animation so consistency with animation is maintained.
Also, please note that I cannot use hash based routing as this split app needs to be displayed in a dialog box.
Below is the dummy code:
App.view.xml
<mvc:View controllerName="com.sap.SplitApp.controller.App" xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" displayBlock="true"
xmlns="sap.m">
<Shell id="shell">
<App>
<SplitApp id="app">
<masterPages>
<Page>
<List items='{/items}' selectionChange="handleNavigate" mode='SingleSelectMaster'>
<items>
<StandardListItem title='{name}' info='{type}'/>
</items>
</List>
</Page>
</masterPages>
<detailPages>
<MessagePage title='Hello!' text='Select a Product'></MessagePage>
<core:Fragment fragmentName="com.sap.SplitApp.fragments.BikeProperties" type="XML"/>
<core:Fragment fragmentName="com.sap.SplitApp.fragments.CarProperties" type="XML"/>
</detailPages>
</SplitApp>
</App>
</Shell>
App.controller.js
onInit: function () {
var items = [
{
name: 'Thunderbird 500cc',
type:'Bike'
},
{
name: 'Swift',
type:'Car'
},
{
name: 'Bullet 350cc',
type:'Bike'
},
{
name: 'Polo',
type:'Car'
}
];
var oModel = new sap.ui.model.json.JSONModel({ items: items});
this.getView().setModel(oModel);
},
handleNavigate: function(oEvent) {
var oBindingContext = oEvent.getParameter("listItem").getBindingContext();
var oSplitApp = this.byId("app");
var oDetailPage = null;
if (oBindingContext.getProperty("type") === "Bike") {
oDetailPage = this.byId('bikePage');
} else {
oDetailPage = this.byId('carPage');
}
oDetailPage.setBindingContext(oBindingContext)
oSplitApp.toDetail(oDetailPage);
}
BikeProperties.fragment.xml
<core:FragmentDefinition
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:l="sap.ui.layout"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core"
>
<Page id='bikePage' title='Bike'>
<Title text='{name}' />
</Page>
</core:FragmentDefinition>
CarProperties.fragment.xml
<core:FragmentDefinition xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core">
<Page id='carPage' title='Car'>
<Title text='{name}'/>
</Page>
So since the API does not offer an obvious way to force an animaton, I looked at the source files.
Your problem is probably from this line from NavContainer.js:
var oFromPage = this.getCurrentPage();
if (oFromPage && (oFromPage.getId() === pageId)) { // cannot navigate to the page that is already current
Log.warning(this.toString() + ": Cannot navigate to page " + pageId + " because this is the current page.");
return this;
}
As you can see from the comment, it is not intended to navigate/animate to the same page that is currently displayed.
One possible solution would be to use a second fragment for both car and bike and to navigate to car2 if you were to be on car1 previously, then to car2 again and so on. This is the best workaround I found.
The following are just some things I found and might be worth to take a further look at, but I couldn't get it to work properly.
I found another line in the source that could be used but there is a catch. The page title bar does not slide as expected. It gets invisible as you can see with this snippet added to your controller in the handleNavigate function:
var oFromPage = oSplitApp.getCurrentDetailPage();
if (oBindingContext.getProperty("type") === "Bike") {
oDetailPage = this.byId("bikePage");
if (oFromPage === oDetailPage) {
sap.m.NavContainer.transitions.slide.to.call(this, this.byId("carPage"), this.byId("bikePage"), function callback() {});
}
} else {
oDetailPage = this.byId("carPage");
if (oFromPage === oDetailPage) {
sap.m.NavContainer.transitions.slide.to.call(this, this.byId("bikePage"), this.byId("carPage"), function callback() {});
}
}
I also noticed that styleClasses are being used for proper transition. The fromPage gets some styles and the toPage too. But since in your case fromPage and toPage are the same, the styleClasses cannot be applied/removed as needed.
oToPage.addStyleClass("sapMNavItemSliding").addStyleClass("sapMNavItemCenter").removeStyleClass("sapMNavItemRight");
oFromPage.addStyleClass("sapMNavItemSliding").removeStyleClass("sapMNavItemCenter").addStyleClass("sapMNavItemLeft");
Using only the "oFromPrage-styleClasses" for your detailsPage results in some sort of "bouncing" from the left side. Using all, one after another, results in wrong navigation.
Maybe you can make some use of these information but as already said, using two car fragments and two bike fragments was the best solution (user-experience-wise) I found.
Have you tried to pass the animation type to the.toDetailPage() method?
https://sapui5.hana.ondemand.com/#/api/sap.m.SplitContainer/methods/toDetail
It accepts a transitionname parameter, right after the page id, and I think this should be working.
Quote from the site:
"The type of the transition/animation to apply. This parameter can be omitted; then the default is "slide" (horizontal movement from the right). Other options are: "fade", "flip", and "show" and the names of any registered custom transitions.
None of the standard transitions is currently making use of any given transition parameters."

Duplicate ID error for fragments in SAP UI5

I have read a number of posts regarding destroying the fragment or page to avoid duplicate ID but the problem here is that a fragment is displayed in the view page and when i press the same button again I get the error Duplicate ID.
Below is the code for fragment and controller :
<core:FragmentDefinition xmlns="sap.m"
xmlns:f="sap.ui.layout.form" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout">
<Page id="masterAp" showHeader="false" enableScrolling="true" >
<TileContainer
id="getTiles"
tiles="{myModel1>/0/TileCollection}">
<StandardTile
title="{myModel1>title}"
icon="{myModel1>icon}"
number="{myModel1>number}"
numberUnit="{myModel1>numberUnit}"
info="{myModel1>info}"
infoState="{myModel1>infoState}"
press="handleTilePress"/>
</TileContainer>
</Page>
</core:FragmentDefinition>
The code for controller : Please advice what line of code is missing to avoid duplicate ID error : Uncaught Error: Error: adding element with duplicate id 'getTiles'
onPressGoToMaster1 : function() {
var oDialogFragment = sap.ui.xmlfragment("yca_web111_dashboard.fragments.panel2",this.getView().getController());
var oModel = new sap.ui.model.json.JSONModel("data/dataAP.json");
sap.ui.getCore().setModel(oModel, "myModel1");
var oPage = this.getView().byId("detail");
oPage.insertContent(oDialogFragment);
this.getSplitAppObj().to(this.createId("detail"));
};
You are trying to add the fragment every time you move to page with id: detail. Simplest solution would be to check if you have already added the fragment.
If yes (fragment is present), don't add the fragment again to page with id: detail, and navigate.
If no (fragment is not present), fetch the fragment, add to page and the navigate.
Code:
onPressGoToMaster1 : function() {
if (!this.oDialogFragment) {
this.oDialogFragment = sap.ui.xmlfragment("yca_web111_dashboard.fragments.panel2",this.getView().getController());
var oModel = new sap.ui.model.json.JSONModel("data/dataAP.json");
sap.ui.getCore().setModel(oModel, "myModel1");
var oPage = this.getView().byId("detail");
oPage.insertContent(this.oDialogFragment);
}
this.getSplitAppObj().to(this.createId("detail"));
};

Filtering data in UI5

The filter using below code is not working. I created an application using a template from Web IDE and then bound OData to the list in XMLView, applying filter on search.
View:
<SearchField liveChange="onSearch" id="master1SearchField" search="onSearch"/>
<List id="master1List" items="{path:'/DetailsSet'}">
<items>
<ObjectListItem id="master1ListItem">
<attributes>
<ObjectAttribute text="{Name}"/>
</attributes>
</ObjectListItem>
</items>
</List>
Controller:
onSearch : function(oEvent) {
var sFilteredValue = oEvent.getSource().getValue();
var oFilter = new sap.ui.model.Filter("Name", sap.ui.model.FilterOperator.Contains, sFilteredValue);
var oElement = this.getView().byId("table");
var oBinding = oElement.getBinding("items");
oBinding.filter([oFilter]);
}
You need to get binding of the items on which the filter need to be applied.
var oElement = this.getView().byId("master1List");
should resolve the issue.
Try to force an update of the control after setting the filter:
oBinding.refresh(true);

How can I add sort items into a fragment dialog?

I have this fragment retrieve by this page https://openui5.hana.ondemand.com/explored.html#/sample/sap.m.sample.TableViewSettingsDialog/code
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core">
<ViewSettingsDialog
confirm="handleConfirm" id='viewSettingsDialogId'>
<sortItems id="sortItemsId">
<!-- <ViewSettingsItem text="Product" key="Name" selected="true" />
<ViewSettingsItem text="Supplier" key="SupplierName" />
<ViewSettingsItem text="Weight" key="WeightMeasure" />
<ViewSettingsItem text="Price" key="Price" /> -->
</sortItems>
</ViewSettingsDialog>
</core:FragmentDefinition>
I want insert manually the sortItems in the control (or by data-binding in the xml-View).
How can I do it?
I try to do it by code in my controller:
//IF CLICK ON SETTINGS BUTTON
handleViewSettingsDialogButtonPressed: function (oEvent) {
if (!this._oDialog) {
this._oDialog = sap.ui.xmlfragment("apps.appIntra.fragment.settingDialog", this);
}
// toggle compact style
jQuery.sap.syncStyleClass("sapUiSizeCompact", this.getView(), this._oDialog);
this._oDialog.open();
var element=sap.ui.getCore().byId("sortItemsId");
this.byId('sortItemsId').addSortItem(new sap.m.ViewSettingsItem({text:"field1", key:"Price"}));
this.byId('sortItemsId').addSortItem(new sap.m.ViewSettingsItem({text:"field2", key:"PLUTO"}));
},
But it not work...
I see this guide http://scn.sap.com/community/developer-center/front-end/blog/2014/02/20/sapui5-dialogwith-businesscard-as-xml-fragment-along-with-controller
but if I use
var element=sap.ui.getCore().byId("sortItemsId");
element value is undefined
The addSortItem is a method that works on the ViewSettingsDialog and not on sortItems.
Therefore, as you have already provided the id viewSettingsDialogId for the ViewSettingsDialog control, in you controller you can do the following,
var oViewSettingsDialog = sap.ui.getCore().byId("viewSettingsDialogId");
oViewSettingsDialog.addSortItem(new sap.m.ViewSettingsItem({text:"field1",
key:"Price"}));
/* and so on... */
This would add the sort items into the sortItems list.