Aggregation binding SAPUi5 from JSON files - sapui5

I am an intern working with SAP UI5, and I am having difficulties accessing the data in my JSON file to a table
My JSON data is in the format as so (This is a snippet):
[
{
"id": 0,
"name": "<UNKNOWN>",
"area": "core",
"cmakeComponents": [
{
"id": "RemoteSupportDaemon",
"name": "RemoteSupportDaemon"
}
],
......
},
{
........
}
]
I am trying to load my JSON files from the manifest.json file as so:
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "opensap_DashAnalytics.i18n.i18n"
}
},
"data": {
"type": "sap.ui.model.json.JSONModel",
"uri": "model/component_XXX.json"
},
"component": {
"type": "sap.ui.model.json.JSONModel",
"uri": "model/component_SSS.json"
}
}
And I am trying to use that data in my view to make a table with:
<!--sap.m.table-->
<Table
id="idTable"
items= "{path:'{data>/}',
mode: 'sap.ui.model.BindingMode.OneWay'}"
.....
>
<headerToolbar>
<Toolbar>
<Title text="Orange"/>
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="Component" />
</Column>
<Column>
<Text text="Number of failed Tests" />
</Column>
<Column>
<Text text="Number of Bugs" />
</Column>
<Column>
<Text text="Total Tests" />
</Column>
<Column>
<Text text="Pass/Fail Ratio" />
</Column>
</columns>
<items>
<ColumnListItem
press= "onItemSelected"
type= "Navigation">
<cells>
<ObjectListItem title="{data>name}"/>
</cells>
.........
.........
</ColumnListItem>
</items>
</Table>
When I run my code, my table displays NO DATA
I have an assumption that the problem has to deal with how I am writing my path variable, or something related.
I was wondering if there were anyone who would be familiar with this problem that could help me.

You have a wrong syntax in table 'items' aggregation
<Table
id="idTable"
items= "{path:'data>/',
mode: 'sap.ui.model.BindingMode.OneWay'}"
>
Furthermore, remember that the number of cells should be the same to the number of columns to work properly
<cells>
<ObjectListItem title="{data>name}"/>
<ObjectListItem title="{data>otherProperty1}"/>
<ObjectListItem title="{data>otherProperty2}"/>
<ObjectListItem title="{data>otherProperty3}"/>
<ObjectListItem title="{data>otherProperty4}"/>
</cells>

Related

SAPUI5 text is not displayed in Selector

I read the documentation https://sapui5.hana.ondemand.com/#/entity/sap.m.Select/sample/sap.m.sample.Select/code and I wanted to created a selector in my code.
I carefully follow the documentation but the text isn't display.
In my XML file:
<Select
selectedKey="{test>/SelectedProduct}"
items="{
path: 'test>/ProductCollection',
sorter: { path: 'Name' }
}">
<core:Item key="{test>/SelectedProduct/ProductId}" text="{test>/SelectedProduct/Name}" />
</Select>
in my controller file:
var oData = {
"SelectedProduct": "HT-1001",
"SelectedProduct2": "HT-1001",
"SelectedProduct3": "HT-1001",
"ProductCollection": [
{
"ProductId": "HT-1000",
"Name": "Notebook Basic 15"
},
{
"ProductId": "HT-1001",
"Name": "Notebook Basic 17"
},
{
"ProductId": "HT-1002",
"Name": "Notebook Basic 18"
},
{
"ProductId": "HT-1002",
"Name": "Notebook Basic 18"
},
{
"ProductId": "HT-1002",
"Name": "Notebook Basic 18"
}
],
"Editable": true,
"Enabled": true
};
var oModel = new JSONModel(oData);
this.getView().setModel(oModel, "test");
It doesn't display me the text but it display me the number of elements of my array.
I also tried:
<Select
selectedKey="{test>/SelectedProduct}"
items="{
path: 'test>/ProductCollection',
sorter: { path: 'Name' }
}">
<core:Item key="{test>/ProductCollection/ProductId}" text="{test>/ProductCollection/Name}" />
</Select>
And:
<Select
selectedKey="{test>/SelectedProduct}"
items="{
path: 'test>/ProductCollection',
sorter: { path: 'Name' }
}">
<core:Item key="{test>/ProductCollection.ProductId}" text="{test>/ProductCollection.Name}" />
</Select>
Why this solution doesn't work as expected ?
No need for ProductCollection in Item binding path. The item path is already set to ProductCollection in Select.
<core:Item key="{test>ProductId}" text="{test>Name}" />

Dynamic Table binding

Please suggest. Table binding does not work.
Model Data and may change:
​{ "TestCloudEnvRO": [ { "pipelineName": "RP1", "cycles": [ "cy1", "cycle1", "RP1cy2", "cyc2", "crCycle" ] }, { "pipelineName": "RP2", "cycles": [ "BP1-c2", "bp2-cy" ] }, { "pipelineName": "RPlocal", "cycles": [ "cyclelocal" ] }, { "pipelineName": "rp1234", "cycles": [ "cyclert" ] }, { "pipelineName": "RPTEST", "cycles": [ "BPTEST1" ] }, { "pipelineName": "rp123", "cycles": [ "cytr" ] } ] }
View
<Table id="idtrlAllPipelines" alternateRowColors="true">
<columns>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="Release Pipeline Cycles"/>
</Column>
</columns>
Controller
var oTemplate = new sap.m.ColumnListItem({ cells: [ new sap.m.Text({ text: "{getHist>pipelineName}" }) ] }); this.byId("idtrlAllPipelines").setModel(oModelEnv, "getHist");
this.byId("idtrlAllPipelines").bindAggregation("items", { path: "getHist>/TestCloudEnvRO", template: oTemplate, templateShareable: true } );
It does not load any items in the table.
But this works at View. I have to replace this with /TestCloudEnvRO with selected key of Icon tab filter, so the above should work. Please suggest.
<Table items="{path: 'getHist>/TestCloudEnvRO'}" id="idtrlAllPipelines" alternateRowColors="true">
For the binding you suggested, your dataset may need to be modified a bit in order to achieve the requirement. PFB the code.
Controller
loadDataSet: function () {
var oMasterModel = this.getView().getModel("oMasterModel");
var oDataSet = [{
"IconTabName": "Env1",
"Table": [{
"name": "Person1",
"runs": ["10", "20"]
}, {
"name": "Person2",
"runs": ["0", "2"]
}]
}, {
"IconTabName": "Env2",
"Table": [{
"name": "Person3",
"runs": ["5", "25"]
}, {
"name": "Person4",
"runs": ["20", "12"]
}]
}];
oMasterModel.setData({
allFilters: oDataSet
});
oMasterModel.refresh(true);
}
View
<IconTabBar items="{oMasterModel>/allFilters}">
<items>
<IconTabFilter text="{oMasterModel>IconTabName}">
<Table items="{oMasterModel>Table}">
<columns>
<Column>
<Label text="Name"/>
</Column>
<Column >
<Label text="Runs"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{oMasterModel>name}"/>
<Select items="{oMasterModel>runs}">
<core:Item text="{oMasterModel>}"/>
</Select>
</cells>
</ColumnListItem>
</items>
</Table>
</IconTabFilter>
</items>
</IconTabBar>

Render Cards dynamically via XML view

Is there a way to render the sap.f.Card control dynamically with an XML view? With aggregation binding maybe? I only used aggregation binding with lists and tables so far...
I need to render some cards dynamically on a main view but I want to stay with the MVC concept. That's why I don't prefer to render the cards in the controller. My Card is also very complex and has multiple controls in it. (Text, Status Indicator, Progress Indicator, etc.)
Is there a way of implementing that?
In Fiori, Cards are usually rendered within sap.f.GridContainer (In fact, it was initially called sap.f.CardContainer).
Just like with Tables and Lists, you can bind <items> to the GridContainer too with the Card as a template control:
<f:GridContainer xmlns:f="sap.f"
width="100%"
snapToRow="true"
items="{
path: '/myCardItems',
templateShareable: false
}">
<f:layout>
<f:GridContainerSettings rowSize="84px" columnSize="84px" gap="8px" />
</f:layout>
<f:layoutXS>
<f:GridContainerSettings rowSize="70px" columnSize="70px" gap="8px" />
</f:layoutXS>
<f:items>
<f:Card> <!-- template -->
<f:header>
<card:Header xmlns:card="sap.f.cards" title="{title}" />
</f:header>
<f:layoutData>
<f:GridContainerItemLayoutData minRows="..." columns="..." />
</f:layoutData>
</f:Card>
</f:items>
</f:GridContainer>
The above snippet is from the Demo Kit sample that has an aggregation binding.
You can achieve it using the Grid layout withcontent aggregation
view.xml
<core:View
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:fc="sap.f"
xmlns:card="sap.f.cards"
controllerName="path.Main"
xmlns:html="http://www.w3.org/1999/xhtml">
<Page title="Main" class="sapUiContentPadding">
<content>
<!-- Cards data binding -->
<l:Grid containerQuery="true" id="cardsGrid" defaultSpan="XL2 L4" class="gridProgressIndicator" hSpacing="0" content="{/cards}">
<fc:Card class="sapUiMediumMargin" width="300px">
<fc:header>
<card:Header
title="{title}"
subtitle="{subTitle}"
iconSrc="{icon}"/>
</fc:header>
<fc:content>
<VBox
height="115px"
class="sapUiSmallMargin"
justifyContent="SpaceBetween">
<HBox justifyContent="SpaceBetween">
<ComboBox
width="120px"
placeholder="To City"
items="{items}">
<core:Item key="{key}" text="{text}" />
</ComboBox>
<ComboBox
width="120px"
placeholder="To City"
items="{items}">
<core:Item key="{key}" text="{text}" />
</ComboBox>
</HBox>
<HBox justifyContent="SpaceBetween">
<DatePicker width="186px" placeholder="Choose Date ..."/>
<Button text="Book" press="onBookPress" type="Emphasized" />
</HBox>
</VBox>
</fc:content>
</fc:Card>
</l:Grid>
</content>
</Page>
</core:View>
controller.js
bindCardsGrid: function() {
var rowData = [
{ "title": "Title 1", "subTitle": "SubTitle 1", "icon": "sap-icon://menu2", "items": [{ "key": "CV1", "text": "CV1"}, { "key": "CV2", "text": "CV2"}, { "key": "CV3", "text": "CV3"},{ "key": "CV4", "text": "CV4"}]},
{ "title": "Title 2", "subTitle": "SubTitle 2", "icon": "sap-icon://add-contact", "items": [{ "key": "CV1", "text": "CV1"}, { "key": "CV2", "text": "CV2"}, { "key": "CV3", "text": "CV3"},{ "key": "CV4", "text": "CV4"}]},
{ "title": "Title 3", "subTitle": "SubTitle 3", "icon": "sap-icon://business-objects-experience", "items": [{ "key": "CV1", "text": "CV1"}, { "key": "CV2", "text": "CV2"}, { "key": "CV3", "text": "CV3"},{ "key": "CV4", "text": "CV4"}]},
{ "title": "Title 4", "subTitle": "SubTitle 4", "icon": "sap-icon://process", "items": [{ "key": "CV1", "text": "CV1"}, { "key": "CV2", "text": "CV2"}, { "key": "CV3", "text": "CV3"},{ "key": "CV4", "text": "CV4"}]}
];
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({ "cards": rowData });
this.getView().setModel(oModel);
},
output

Cant load the image src link from the JSON file in the view of the project

I am able to bind the CourseName and Text to the view but is not able to bind the Image link to the view (in the Image src)
code for view is as follows :-
<mvc:View controllerName="Workspace.controller.MasterData" xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc"
xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
<Shell>
<App class="sapUiResponsiveMargin" width="auto">
<pages>
<Page title="{i18n>MasterDataTitle}" backgroundDesign="Transparent" showNavButton="true" navButtonPress="onNavBack">
<l:Grid class="sapUiSmallMarginTop" hSpacing="2" defaultSpan="L6 M6 S10" id="grid1">
<l:content>
<VBox items="{course>/Courses}">
<items>
<Image src="{course>Image}" width="100%" press="CreateDataButton">
<layoutData>
<l:GridData span="L3 M3 S8" linebreakL="true" linebreakM="true" linebreakS="true"/>
</layoutData>
</Image>
<VBox >
<Text text="{course>CourseName}"/>
<Text text="{course>Text}"/>
</VBox>
</items>
</VBox>
</l:content>
</l:Grid>
</Page>
</pages>
</App>
</Shell>
The JSON file is as follows :- (course.json)
{
"Courses": [{
"CourseName": "JAVA",
"Text": "Java is a general-purpose computer-programming language ",
"Image" :"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAACgCAMAAADthaR8AAAAwFBMVEX"
}, {
"CourseName": "C++",
"Text": "Hypertext Preprocessor is a server-side scripting language designed for web development. ",
"Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAACgCAMAAADthaR8AAAAwFBMVEX"
}, {
"CourseName": "PHP",
"Text": "C++ is a general-purpose programming language. ",
"Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJoAAABNCAMAAABpGo2yAAAAY1BMVEX///8AAAA/Pz/r6+uFhYX39"
}, {
"CourseName": "JAVASCRIPT",
"Text": "SQL is a domain-specific language used in programming and designed .",
"Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAMAAAC8EZcfAAAAeFBMVEX33x4AAAD74x9JQgnUwBrx2h0sKAX/6B/+5R+WiBL/6h"
}, {
"CourseName": "SQL",
"Text": "SQL is a domain-specific language used in programming and designed ",
"Image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAO0AAADVCAMAAACMuod9AAAA+VBMVEX///8mh84Acsa6ury41DJ/ugAAacO80usUeskkhs4kitC2trgAf8vv7+"
}]
}

Filtering on Nested Aggregation Binding

I want to be able to apply a filter to a nested aggregation binding, but it doesn't seem to work. Here is the XML:
<l:Grid id="test" defaultSpan="L6 M6 S6" content="{path : 'test>/', templateShareable:false}">
<l:content>
<VBox width="100%">
<HBox height="100px" alignItems="Center" justifyContent="Start">
<VBox alignItems="Center" width="25%">
<core:Icon src="{test>icon}" width="100%" />
<Text text="{test>text}" width="100%"/>
</VBox>
<VBox id="test" height="80px" items="{path: 'test>data/', templateShareable:false}">
<Link text="{parts: [{ path: 'test>key'},
{ path: 'test>value' }],
formatter : 'dostuff'}"/>
</VBox>
</HBox>
</VBox>
</l:content>
</l:Grid>
And my JSON data is as follows:
{
"results": [{
"text": "object1",
"icon": "icon1",
"data": [{
"value1": "foo",
"value2": "bar"
}, {
"value1": "john",
"value2": "smith"
}]
},
{
"text": "object2",
"icon": "icon2",
"data": [{
"value1": "adam",
"value2": "bobson"
}, {
"value1": "john",
"value2": "smith"
}, {
"value1": "whatever",
"value2": "work please"
}]
}
]
}
I want to be able to filter on test>/results/[n]/data/[n]/[value1 + value2] and have the gird filtered at that level. Whatever I try, it only filters on the Grid content because I can't seem to get the binding for the in VBox "test".
Cheers,
James
Are you trying to filter the content dynamically from JS? Or statically from the XML directly? I assume that you want to do it from JS.
Your VBox with id test is inside a Grid whose content aggregation you have binded. This means that the whole VBox inside the grid (including the test VBox) is treated as a template for the content aggregation of the grid (i.e. with our JSON, you will end up having two copies of the VBox).
Using this.byId("test") will clearly not work, as it will return a control which is part of the Grid's content aggregation template. So be able to filter the inner VBoxes (because there will be several of them depending on the contents of the model), you have to iterate through the contents of the grid and apply the filtering to each of the target VBoxes. Something along the lines of:
this.byId("grid").getContent().forEach(function(oVbox) {
// need to get the HBox and the second VBox from it.
oVbox.getItems()[0].getItems()[1].getBinding("items").filter(...);
});
Also, both the Grid and the VBox have the same IDs, so your code will fail because of that as well. Generally, you don't need to define an ID for an aggregation template or a child.