sapui5 access to controller without id - sapui5

i'm new at sapui5. I have a List where each element contains a Button and an Image. I want to change the image src by pressing button (only imagewhich is part of list element same as button). Is it possible to get access to image withou id? (How to do it?)
Xml code:
<List items="{data>/Stages}">
<CustomListItem>
<Panel>
<headerToolbar>
<Toolbar class="topDetailToolbar" style="Clear">
<Title class="sapUiSmallMarginBegin fieldWorkTitle" text="{data>Name}" titleStyle="H2" />
<ToolbarSpacer />
<Button text="{i18n>TECH_CARD_ROLL}" class="addButton sapUiSmallMarginBottom" press="onVisibleFilters" />
<core:Icon src="sap-icon://navigation-up-arrow" size="1rem" color="#00c0db" visible="{confFilter>/filterUp}" />
</Toolbar>
</headerToolbar>
</Panel>
</CustomListItem>
</List>

You can achieve it by adding the style class to icon and get the instance of the icon using jQuery and reset using setSrc()
Event handler - onVisibleFilters to change the icon src
onVisibleFilters: function(oEvent) {
var oToolbarId = oEvent.getSource().getParent().sId;//get Parent toolbar of button
var sIconId = jQuery("#" + oToolbarId).find(".hdrIcon").attr("id");//get Icon id using jQuery and hdrIcon class
if(sIconId) {
var oIcon = sap.ui.getCore().byId(sIconId);
if(oIcon) oIcon.setSrc("sap-icon://lab");//update the icon src
}
}

Here's what you should do:
var oButton = oEvent.getSource(); //this returns the button which triggers the press event
var oListItem = oButton.getParent(); //returns the listItem in which the button was pressed
var aCells = oListItem.getAggregation("cells");
you should be able to find the image in one of the indexes in the cells array.

Related

Add button in sap.m.list row

I want to add buttons to each row in my sap.m.List. On that button I want to open a popup to display further details without navigating to another page.
Any code snippet or examples out there how I can add buttons to each row and bind them to fetch data from another model.
Instead of the StandardListItem you need a CustomListItem. There you can add any control you like:
<List headerText="Custom Content" items="{path: '/ProductSet'}" >
<CustomListItem>
<HBox>
<Label text="{ProductName}"/>
<Button text="More Infos" click="onPressMoreInfos" />
</HBox>
</CustomListItem>
</List>
I think the tricky part here is the binding. One CustomListItem is bound to a single entity of your set. If you add a Button to your CustomListItem (or any other control) they are also automatically bound to the specific entity.
So in your click handler you can do the following:
onPressMoreInfos: function(oEvent) {
var oButton = oEvent.getSource();
// if your model has a name, don't forget to pass it as a parameter
var oContext = oButton.getBindingContext();
// create the popover, either here or in a new method
var oPopover = this.getTheInfoPopover();
// if your model has a name, don't forget to pass it as the second parameter
oPopover.setBindingContext(oContext);
}
Then your Popover has the same binding information as the list item and you can access every property of the specific entity.
Try below code to add a button to each row, in your XML view:
<columns>
<Column id="userNameColumn">
<Text text="userNameLabelText" />
</Column>
<Column id="buttonColumn">
<Text text="Button" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Input value="{UserName}"/>
</cells>
<Button id="buttonId" icon="sap-icon://add" press="handleResponsivePopoverPress"></Button>
</ColumnListItem>
</items>
Controller to handle button press, see example here
https://sapui5.hana.ondemand.com/#/sample/sap.m.sample.ResponsivePopover/preview
You can use sap.m.CustomListItem as a template for items aggregation. There is a sample here. You can add any control to the item.

Data Binding from TableSelectDialog to Form

I'm using TableSelectDialog to view some Carrier details. All I need is: If I select any item (row), then all the values from that row should get automatically populated to the form input fields.
In the attached image, if Carrier Name is selected from TableSelectDialog, then the remaining fields should be populated based on that value.
You can achieve the required functionality using the Binding context that you receive from the TableSelcect Dialog.
But for binding context to work properly, both form and the table select dialog should refer to the same Model.
Below is the working code:
VIEW.XML:
Has a Button to trigger the table select dialog.
Has a form.
<l:VerticalLayout class="sapUiContentPadding" width="100%">
<l:content>
<Button class="sapUiSmallMarginBottom" text="Show Table Select Dialog"
press="handleTableSelectDialogPress">
</Button>
<VBox class="sapUiSmallMargin">
<f:SimpleForm id="SimpleFormDisplay354">
<f:content>
<Label text="Supplier Name" />
<Text id="nameText" text="{SupplierName}" />
<Label text="Description" />
<Text text="{Description}" />
<Label text="ProductId" />
<Text text="{ProductId}" />
<Label text="Quantity" />
<Text id="countryText" text="{Quantity}" />
</f:content>
</f:SimpleForm>
</VBox>
</l:content>
</l:VerticalLayout>
Controller:
onInit: function () {
// set explored app's demo model on this sample
var oModel = new JSONModel(jQuery.sap.getModulePath("sap.ui.demo.mock", "/products.json"));
this.getView().setModel(oModel);
},
handleTableSelectDialogPress: function (oEvent) {
if (!this._oDialog) {
this._oDialog = sap.ui.xmlfragment("sap.m.sample.TableSelectDialog.Dialog", this);
}
this.getView().addDependent(this._oDialog);
// toggle compact style
this._oDialog.open();
},
handleClose: function (oEvent) {
var aContexts = oEvent.getParameter("selectedContexts");
if (aContexts && aContexts.length) {
// MessageToast.show("You have chosen " + aContexts.map(function(oContext) { return oContext.getObject().Name; }).join(", "));
this.byId('SimpleFormDisplay354').setBindingContext(aContexts[0]);
}
oEvent.getSource().getBinding("items").filter([]);
}
Now, we also have a Select dialog and on click of any Item we call method : handleClose
In handleClose, we obtain the clicked Item binding context and then tell the form : hey! refer to this context ( which is present in the model). Binding context has a path which tells the form from where to do the relative binding.
Please feel free to contact for more information.

add second filter without removing the existing ones

Hi i have a searchfield with this code behind it:
onSearch : function (oEvent) {
if (oEvent.getParameters().refreshButtonPressed) {
// Search field's 'refresh' button has been pressed.
// This is visible if you select any master list item.
// In this case no new search is triggered, we only
// refresh the list binding.
this.onRefresh();
} else {
var andFilter = [];
var sQuery = oEvent.getParameter("query");
if (sQuery && sQuery.length > 0) {
// add filters
var oTableSearchState = [];
oTableSearchState = [new Filter("Supplier", FilterOperator.Contains, sQuery), new Filter("BusArea", FilterOperator.Contains, sQuery), new Filter("CostCenter", FilterOperator.Contains, sQuery),
new Filter("FuncArea", FilterOperator.Contains, sQuery)];
andFilter.push(new Filter(oTableSearchState, false));
}
this._applySearch(andFilter);
}
},
And a filter button that should add aditional filters. Something like this:
onSetFilter : function(oEvent) {
var andFilter = [];
andFilter.push(new Filter("BusArea", FilterOperator.EQ, "5000"));
this._applySearch(andFilter);
},
But of course the "BusArea" part should be dependent on what filters are selected. It could be more than 1 filter. the _applySearch function looks like this:
_applySearch: function(andFilter) {
var oViewModel = this.getModel("worklistView");
this._oTable.getBinding("items").filter(andFilter, true);
// changes the noDataText of the list in case there are no filter results
if (andFilter.length !== 0) {
oViewModel.setProperty("/tableNoDataText",
this.getResourceBundle().getText("worklistNoDataWithSearchText"));
}
}
the problem is that when i add a filter via the filter button, the filters from the searchbar disappear and the other way arround. how can i change my code so that i can add the filters without removing the existing ones?
One solution is to get the Filters from the binding info and push back together with the new Filter using and.
this._oTable.getBindingInfo("items").filters.aFilters;
After our conversation on the chat, I have made this snippet using a global model.
https://jsbin.com/pewavuhonu/edit?html,output
The ComboBox and the Button simulates your Dialog.
The input simulates the SearchField
Both are binded against the global "filtersModel", and both call the _calculateFilters() function when submiting the info
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta charset="utf-8">
<title>MVC with XmlView</title>
<!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
<script id='sap-ui-bootstrap'
src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js'
data-sap-ui-theme='sap_bluecrystal'
data-sap-ui-libs='sap.m'
data-sap-ui-xx-bindingSyntax='complex'></script>
<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
<!-- define a new (simple) View type as an XmlView
- using data binding for the Button text
- binding a controller method to the Button's "press" event
- also mixing in some plain HTML
note: typically this would be a standalone file -->
<script id="view1" type="sapui5/xmlview">
<mvc:View xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" controllerName="my.own.controller">
<Panel headerText="Filters">
<VBox>
<HBox>
<Label text="Filter by Customer:" class="sapUiSmallMarginTop sapUiSmallMarginEnd"/>
<ComboBox id="comboBox" selectedKey="{filtersModel>/customerFilter}">
<items>
<core:Item key="VINET" text="VINET" />
<core:Item key="TOMSP" text="TOMSP" />
<core:Item key="HANAR" text="HANAR" />
<core:Item key="VICTE" text="VICTE" />
<core:Item key="SUPRD" text="SUPRD" />
</items>
</ComboBox>
<Button text="Apply this Filter" press="_calculateFilters"></Button>
</HBox>
</VBox>
<VBox>
<HBox>
<Input value="{filtersModel>/shipAddressFilter}" id="input" submit="_calculateFilters" width="500px" placeholder="Filter by ShipAddress: Write and enter for filtering"/>
</HBox>
</VBox>
</Panel>
<Panel>
<List id="list" items="{/Orders}">
<StandardListItem title="{CustomerID}" info="{ShipAddress}"/>
</List>
</Panel>
</mvc:View>
</script>
<script>
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
onInit: function(){
var oFiltersModel = new sap.ui.model.json.JSONModel();
sap.ui.getCore().setModel(oFiltersModel, "filtersModel");
},
_calculateFilters: function(){
var oSelect = this.getView().byId("comboBox"),
oListBinding = this.getView().byId("list").getBinding("items"),
oFiltersModel = sap.ui.getCore().getModel("filtersModel"),
oCustomerFilterValue = oFiltersModel.getProperty("/customerFilter"),
oShipAddressValue = oFiltersModel.getProperty("/shipAddressFilter"),
oFilters = [];
if(oCustomerFilterValue){
oFilters.push(new sap.ui.model.Filter("CustomerID", "EQ", oCustomerFilterValue));
}
if(oShipAddressValue){
oFilters.push(new sap.ui.model.Filter("ShipAddress", "Contains", oShipAddressValue));
}
oListBinding.filter(oFilters);
}
});
/*** THIS IS THE "APPLICATION" CODE ***/
// create some dummy JSON data
var data = {
actionName: "Say Hello"
};
// instantiate the View
var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
// create a Model and assign it to the View
var uri = "https://cors-anywhere.herokuapp.com/services.odata.org/Northwind/Northwind.svc"; // local proxy for cross-domain access
var oModel = new sap.ui.model.odata.ODataModel(uri, {
maxDataServiceVersion: "2.0"
});
myView.setModel(oModel);
// put the View onto the screen
myView.placeAt('content');
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>

Nested lists: get selected item of inner list?

As part of my SAPUI5 application i have a list which can be used to navigate to detail pages for the selected item. Now for every list item there is also a choice for a "mode" which can be selected from a list aswell (=> nested list).
This is how the view looks like:
<List id="competitionList" items="{
path: 'competitions>/results'
}">
<items>
<CustomListItem
type="Navigation"
press="onPress">
<VBox>
<Text text="{
path: 'competitions>time',
formatter: '.getDescription'
}"/>
<SelectList id="mode-select">
<items>
<core:Item key="full" text="Full"/>
<core:Item key="one" text="Short"/>
</items>
</SelectList>
</VBox>
</CustomListItem>
</items>
</List>
As you can see there is a SelectList inside the standard List. That SelectList will be filled according to some values inside the bound competition.
Now my question is: How can i determine which item got selected in the SelectList inside the onPress function for the pressed item of the parent List?
My onPress function currently looks like this:
onPress: function(oEvent) {
var oItem = oEvent.getSource();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("startlist", {
showId: showId,
competitionId: oItem.getBindingContext("competitions").getProperty("number")
});
}

adding element with duplicate id

I am creating a SAP Fiori application. I have input in a dialog box in that I have to fetch the input value. I am defining the dialog in fragment view.
When I try to give the id for input I am getting an error as adding element with duplicate id.
------ Fragment View------
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:app="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1">
<Dialog title="Title" class="sapUiPopupWithPadding" >
<content>
<HBox>
<items>
<Text text="Name"></Text>
<Input value="" id="myId" > </Input>
</items>
</HBox>
</content>
<beginButton>
<Button text="Ok" press="DialogButton" />
</beginButton>
</Dialog>
---Controller Code---
DialogButton:function(oEvent) {
var myIdValue=sap.ui.getCore().byId("myId").getValue();
console.log("ID Value :::"+ myIdValue);
oDialogFragment.close();
}
You create a new dialog fragment instance every time you need to open the dialog .
This will cause the duplicated ID issue. Please keep a dialog fragment instance in your controller.
Please see the sample code:
DialogButton:function(oEvent) {
if(!this.oDialog) {
this.oDialog = sap.ui.xmlfragment("you.dialog.id", this );
}
this.oDialog.open();
}
take a look at the following help
IDs in Declarative XML or HTML Fragments you need to add an ID when the fragment is instantiated, that way the control has a prefix which is unique
It is also a good idea to add your fragment as dependant to your main view. This way it will be destroyed when the main view is destroyed. And you will not get duplicate id error when navigating away from your view and back.
DialogButton:function(oEvent) {
if(!this.oDialog) {
this.oDialog = sap.ui.xmlfragment("you.dialog.id", this );
this.getView().addDependent(this.oDialog);
}
this.oDialog.open();
}