We defined our models in Manifest.Json after i18n model.
"UpperBody": {
"type": "sap.ui.model.json.JSONModel"
},
"LowerBody": {
"type": "sap.ui.model.json.JSONModel"
}
We defined our libraries in the Controller.js file.
sap.ui.define([
"sap/ui/core/mvc/Controller",
'sap/ui/model/json/JSONModel'
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller ,JSONModel)
We created 2 JSON files inside the model folder under the Web App

{
"Exercise": [{
"Name": "Leg Extension",
"Muscle Group": "Leg",
"Weights": "65 kg ",
"Reps and Sets" : "8-10 reps 4 sets"
},{
"Name": "Calf Raise Machine",
"Muscle Group": "Leg",
"Weights": "50 kg ",
"Reps and Sets" : "8-10 reps 4 sets"
},{
"Name": "Leg Press",
"Muscle Group": "Leg",
"Weights": "70 kg ",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Leg Curl",
"Muscle Group": "Leg",
"Weights": "60 kg ",
"Reps and Sets" : "8-10 reps 4 sets"
}
]
}
{
"Exercise": [{
"Name": "Dumbbell Press",
"Muscle Group": "Chest",
"Weights": "30 kg Dumbbells",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Dumbbell Fly",
"Muscle Group": "Chest",
"Weights": "17,5 kg Dumbbells",
"Reps and Sets" : "12-15 reps 4 sets"
},
{
"Name": "Incline Bench Press",
"Muscle Group": "Chest",
"Weights": "45 kg without bar",
"Reps and Sets" : "10-12 reps 4 sets"
},
{
"Name": "Butterfly",
"Muscle Group": "Chest",
"Weights": "45 kg",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Chest Press Machine",
"Muscle Group": "Chest",
"Weights": "60 kg",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Lat Pulldown Wide",
"Muscle Group": "Back",
"Weights": "60 kg",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Seated Row",
"Muscle Group": "Back",
"Weights": "60 kg",
"Reps and Sets" : "12-15 reps 4 sets"
},
{
"Name": "Back Extension",
"Muscle Group": "Back",
"Weights": "Body Weight",
"Reps and Sets" : "15-25 reps 4 sets"
},
{
"Name": "Lat Pulldown Narrow",
"Muscle Group": "Back",
"Weights": "60 kg",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Military Press",
"Muscle Group": "Shoulder",
"Weights": "30 kg",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Shrug",
"Muscle Group": "Shoulder",
"Weights": "30 kg Dumbbells",
"Reps and Sets" : "8-10 reps 4 sets"
},
{
"Name": "Lateral Raise",
"Muscle Group": "Shoulder",
"Weights": "10 kg dumbbells",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Face Pull",
"Muscle Group": "Shoulder",
"Weights": "50 kg",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Z Bar Curl",
"Muscle Group": "Biceps Arm",
"Weights": "25 kg",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Dumbbell Curl",
"Muscle Group": "Biceps Arm",
"Weights": "12.5 kg Dumbbells",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Hammer Curl",
"Muscle Group": "Biceps Arm",
"Weights": "15 kg Dumbbells",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Rope Pushdown",
"Muscle Group": "Triceps Arm",
"Weights": "40 kg ",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Skull Crusher",
"Muscle Group": "Triceps Arm",
"Weights": "30 kg ",
"Reps and Sets" : "15 reps 4 sets"
},
{
"Name": "Overhead Dumbbell Triceps Extension",
"Muscle Group": "Triceps Arm",
"Weights": "20 kg ",
"Reps and Sets" : "15 reps 4 sets"
}
]
}
In the onInit function, we first call the models we created and then bind our JSON files using the syntax ‘application namespace/modulename/model/Json file name’.
onInit: function () {
var oModel = this.getOwnerComponent().getModel("UpperBody");
oModel.loadData(sap.ui.require.toUrl("fitness/weights/model/UpperBody.json"));
var oModel2 = this.getOwnerComponent().getModel("LowerBody")
oModel2.loadData(sap.ui.require.toUrl("fitness/weights/model/LowerBody.json"))
We opened Google Chrome Dev Tools with F12 and added a debug point at the end.

Then, after pressing Refresh and falling into the debug mode, we test if oModel and oModel2 are coming or not. If you receive an undefined error here, you can check the path or model name in your JavaScript code.

Afterward, we add the libraries we will use to the MainView XML file. We create an Icon Tab structure.
<mvc:View controllerName="fitness.weights.controller.Main"
xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
xmlns="sap.m"
xmlns:core="sap.ui.core">
<Page id="page" title="{i18n>title}">
<content >
<IconTabBar id="idIconTabBarNoIcons" expanded="{device>/isNoPhone}" class="sapUiResponsiveContentPadding">
<items>
<IconTabFilter id="UpperBody" text="UpperBody" key="info">
</IconTabFilter>
<IconTabFilter id="LowerBody" text="LowerBody" key="info">
</IconTabFilter>
</items>
</IconTabBar>
</content>
</Page>
</mvc:View>
We have created 2 tabs on our screen.

“Then, inside the WebApp folder (be careful not to get a pathing error :D), we create the fragments of the tabs we will use and the filterbars we will use in those tabs. The file should be named ‘YourGivenName.fragment.xml’.”

First, we will define our main fragments. After adding the core library to the beginning of the UpperBody fragment, we add a Table. We give it an ID to use later and bind it to the syntax ‘(Model Name> JSON Object Name (if not, you can leave it blank))’ in the items section. Then we give the names from the JSON to the columns. Afterward, using the syntax ‘(Model Name> Property Name)’ with columnListItem, we place the data into the columns
Ardından MainView.xml’de bu fragmenti ekliyoruz.
<c:FragmentDefinition
xmlns="sap.m"
xmlns:c="sap.ui.core"
xmlns:core="sap.ui.core"
>
<Table items="{UpperBody>/Exercise}" id="ExerciseTable">
<columns>
<Column>
<Text text="Name" />
</Column>
<Column>
<Text text="Muscle Group" />
</Column>
<Column>
<Text text="Weights" />
</Column>
<Column>
<Text text="Rep and Sets" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{UpperBody>Name}" />
<Text text="{UpperBody>Muscle Group}" />
<Text text="{UpperBody>Weights}" />
<Text text="{UpperBody>Reps and Sets}" />
</cells>
</ColumnListItem>
</items>
</Table>
</c:FragmentDefinition>
<c:FragmentDefinition
xmlns="sap.m"
xmlns:c="sap.ui.core"
xmlns:core="sap.ui.core"
>
<Table items="{LowerBody>/Exercise}" id="ExerciseTable2">
<columns>
<Column>
<Text text="Name" />
</Column>
<Column>
<Text text="Muscle Group" />
</Column>
<Column>
<Text text="Weights" />
</Column>
<Column>
<Text text="Rep and Sets" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{LowerBody>Name}" />
<Text text="{LowerBody>Muscle Group}" />
<Text text="{LowerBody>Weights}" />
<Text text="{LowerBody>Reps and Sets}" />
</cells>
</ColumnListItem>
</items>
</Table>
</c:FragmentDefinition>
The syntax should be as follows.
<core:Fragment fragmentName="applicationnamespace.modulename.Fragments.FragmentName" type="XML" />
<IconTabFilter id="UpperBody" text="UpperBody" key="info">
<core:Fragment fragmentName="fitness.weights.Fragments.UpperBody" type="XML" />
</IconTabFilter>
<IconTabFilter id="LowerBody" text="LowerBody" key="info">
<core:Fragment fragmentName="fitness.weights.Fragments.LowerBody" type="XML" />
</IconTabFilter>


Then, we define the FilterBars we will use inside these Fragments in FilterBar Fragments. Here, we define the objects that will appear in the FilterBar. After giving a unique ID to the MultiComboBox and giving the function names we will use in JavaScript, we give a Placeholder and set Required to true because I want it to be required. If you don’t want it to be required, you can say false. Since we will use the filter structure, after giving the path of the items, we specify which property to sort by. Then, we bind the items that will come to this MultiComboBox using the syntax ‘(Model Name> Property Name)’.
<c:FragmentDefinition xmlns="sap.m" xmlns:c="sap.ui.core" xmlns:fb="sap.ui.comp.filterbar" xmlns:core="sap.ui.core">
<fb:FilterBar showClearOnFB="true" id="filterbar2" persistencyKey="myPersKey" useToolbar="false" search=".onSearch" clear="ClearFilterbar" filterChange=".onFilterChange" afterVariantLoad=".onAfterVariantLoad">
<fb:filterItems>
<fb:FilterItem name="Name" label="Name">
<fb:control>
<MultiComboBox
id="LowerBodyName"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Exercise Name"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Name}" text="{LowerBody>Name}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Weights" label="Weights">
<fb:control>
<MultiComboBox
id="LowerBodyWeights"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Weight"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Weights}" text="{LowerBody>Weights}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Reps and Sets" label="Reps and Sets">
<fb:control>
<MultiComboBox
id="LowerBodyRepsandSets"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Reps and Sets"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Reps and Sets}" text="{LowerBody>Reps and Sets}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
</fb:filterItems>
</fb:FilterBar>
</c:FragmentDefinition>
<c:FragmentDefinition xmlns="sap.m" xmlns:c="sap.ui.core" xmlns:fb="sap.ui.comp.filterbar" xmlns:core="sap.ui.core">
<fb:FilterBar showClearOnFB="true" id="filterbar2" persistencyKey="myPersKey" useToolbar="false" search=".onSearch" clear="ClearFilterbar" filterChange=".onFilterChange" afterVariantLoad=".onAfterVariantLoad">
<fb:filterItems>
<fb:FilterItem name="Name" label="Name">
<fb:control>
<MultiComboBox
id="LowerBodyName"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Exercise Name"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Name}" text="{LowerBody>Name}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Weights" label="Weights">
<fb:control>
<MultiComboBox
id="LowerBodyWeights"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Weight"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Weights}" text="{LowerBody>Weights}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Reps and Sets" label="Reps and Sets">
<fb:control>
<MultiComboBox
id="LowerBodyRepsandSets"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Reps and Sets"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
>
<core:Item key="{LowerBody>Reps and Sets}" text="{LowerBody>Reps and Sets}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
</fb:filterItems>
</fb:FilterBar>
</c:FragmentDefinition>
Afterwards, we define the FilterBar Fragments we created inside the other Fragments before the Table.
<core:Fragment fragmentName="fitness.weights.Fragments.UpperBodyFilterBar" type="XML" />
core:Fragment fragmentName="fitness.weights.Fragments.LowerBodyFilterBar" type="XML" />


Then, we write the function that we will use for filtering in the Controller Js. Since the 2 tables are different from each other, we define 2 arrays. Then, we access our Multicombox with this.byId and assign the selected item to a variable. After that, we define a for loop that will loop based on the number of selected items. We assign the selected item to a variable using .getKey(). Then, we create a filter and match the “Property Name” with the selected value, and push it into our filter array. After doing this for other filter bars, we define a variable for each of our tables using their ids. Then, we create Binding variables by using getBinding(“items”) from these tables. We filter these Binding variables with the filter arrays we created.
onSearch: function () {
var aFilters = [];
var aFilters2 = [];
var aSelectedItems = this.byId("UpperBodyName").getSelectedItems();
for (var i = 0; i < aSelectedItems.length; i++) {
var sValue = aSelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Name",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters.push(oFilter);
}
var a2SelectedItems = this.byId("UpperBodyMuscleGroup").getSelectedItems();
for (var i = 0; i < a2SelectedItems.length; i++) {
var sValue = a2SelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Muscle Group",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters.push(oFilter);
}
var a3SelectedItems = this.byId("UpperBodyWeights").getSelectedItems();
for (var i = 0; i < a3SelectedItems.length; i++) {
var sValue = a3SelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Weights",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters.push(oFilter);
}
var a4SelectedItems = this.byId("LowerBodyName").getSelectedItems();
for (var i = 0; i < a4SelectedItems.length; i++) {
var sValue = a4SelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Name",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters2.push(oFilter);
}
var a5SelectedItems = this.byId("LowerBodyWeights").getSelectedItems();
for (var i = 0; i < a5SelectedItems.length; i++) {
var sValue = a5SelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Weights",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters2.push(oFilter);
}
var a6SelectedItems = this.byId("LowerBodyRepsandSets").getSelectedItems();
for (var i = 0; i < a6SelectedItems.length; i++) {
var sValue = a6SelectedItems[i].getKey();
var oFilter = new sap.ui.model.Filter(
"Reps and Sets",
sap.ui.model.FilterOperator.EQ,
sValue
);
aFilters2.push(oFilter);
}
var oTable = this.byId("ExerciseTable");
var oTable2 = this.byId("ExerciseTable2");
var oBinding = oTable.getBinding("items");
var oBinding2 = oTable2.getBinding("items");
oBinding.filter(aFilters);
oBinding2.filter(aFilters2);
}
Great! Now the user can filter the data in the table using the combo box on the screen.


Finally, when the Clear button is pressed, we define a new model in Manifest.json to clear the Filterbar
"Filter": {
"type": "sap.ui.model.json.JSONModel"
}
Afterward, we add the Selected Keys property to the MultiComboboxes.
<MultiComboBox
id="UpperBodyName"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Exercise Name"
required="true"
items="{ path: 'UpperBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/Names}"
>
<core:Item key="{UpperBody>Name}" text="{UpperBody>Name}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Muscle Group" label="Muscle Group">
<fb:control>
<MultiComboBox
id="UpperBodyMuscleGroup"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Muscle Group"
required="true"
items="{ path: 'UpperBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/MuscleGroup}"
>
<core:Item key="{UpperBody>Muscle Group}" text="{UpperBody>Muscle Group}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Weights" label="Weights">
<fb:control>
<MultiComboBox
id="UpperBodyWeights"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Weight"
required="true"
items="{ path: 'UpperBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/Weights}"
>
<core:Item key="{UpperBody>Weights}" text="{UpperBody>Weights}" />
</MultiComboBox>
<MultiComboBox
id="LowerBodyName"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Exercise Name"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/Names}"
>
<core:Item key="{LowerBody>Name}" text="{LowerBody>Name}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Weights" label="Weights">
<fb:control>
<MultiComboBox
id="LowerBodyWeights"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Weight"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/Weights}"
>
<core:Item key="{LowerBody>Weights}" text="{LowerBody>Weights}" />
</MultiComboBox>
</fb:control>
</fb:FilterItem>
<fb:FilterItem name="Reps and Sets" label="Reps and Sets">
<fb:control>
<MultiComboBox
id="LowerBodyRepsandSets"
selectionChange="handleSelectionChange"
selectionFinish="handleSelectionFinish"
width=""
placeholder="Choose Reps and Sets"
required="true"
items="{ path: 'LowerBody>/Exercise', templateShareable: true, sorter: { path: 'Name' }, parameters: {distinct: true}}"
selectedKeys="{Filter>/Reps and Sets}"
>
<core:Item key="{LowerBody>Reps and Sets}" text="{LowerBody>Reps and Sets}" />
</MultiComboBox>
Afterward, I add my function to my Controller with the name I gave to the Clear Property of the Filterbar.
Here, after receiving the Filter Model I created, we use the comma empty array syntax next to the Property Name entered in the Selected Keys section of the Multicombobox, allowing the user-entered filters to be cleared when the Clear button is pressed.
ClearFilterbar: function () {
var oFilterModel = this.getView().getModel("Filter");
oFilterModel.setProperty("/Names", []);
oFilterModel.setProperty("/Weights", []);
oFilterModel.setProperty("/Reps and Sets", []);
oFilterModel.setProperty("/MuscleGroup", []);
}
You can access the code from the following repository.
https://github.com/kaancancalkan/Medium-Blog/tree/main/Fitness%20Weights/weights
No Comments