Attach browser event to a control using XML-View - sapui5

My REST service send me a lot of data. Every property contains the value and a help-attribute that contains a long description of the field property.
Ok, I have data (a list of property with value and help) in a JSONModel and I use data-binding XML https://openui5.hana.ondemand.com/#docs/guide/91f0f3cd6f4d1014b6dd926db0e91070.html to map data value in forms and tables.
Now I want show somehow help message for each property.
My idea is show a message dialog when the user double-click on the Label or on the Text of the column header in a table
Both Label and Text have attachBrowserEvent method but I don't know how use the function to attach the event wrinting only in the XML-views
I would like something like this:
In XML-View:
<Label text="Language"
attachBrowserEvent:"function("click",showMessageHelp({model>/language/help}))">
<Input value="{model>/language/value}"/>
In the controller:
showMessageHelp:function(sMessage){
//show message dialog with sMessage
...........
}

You can achieve this using onAfterRendering method.
Have CustomData in the XML:
<Label id="label" text="Language">
<customData>
<core:CustomData key="type" value="{/language/help}" />
</customData>
</Label>
Then in controller use this customData:
onAfterRendering: function () {
var showValueHelp = function () {
var text = this.getCustomData()[0].getValue();
sap.m.MessageToast.show(text);
event.preventDefault();
event.stopPropagation();
return false;
};
this.byId("label").attachBrowserEvent("click", showValueHelp);
}
JS fiddle is here
PS:I am not sure this is viable solution for you.
This is the best I could come up with, currently.

Attach a browser event for each label is possible but I can't find a way to do it without repeat each label id.
I have found an alternative solution: my data are shown in forms and tables.
I have added on the right of each form couple of label: value a Text element with the help info:
<Label text="Field duck"/>
<Text text="{model>/elements/mainFields1/duck/value}"/>
<Text text="{model>/elements/mainFields1/duck/ATTR/help/description}" visible="{ui>/bShowHelp}" />
In tables I have divided each column title in two group: header and footer; in the footer I have placed the help info:
<Column>
<header>
<Text text="Name"/>
</header>
<footer>
<Text text="{model>/elements/airports/templateNewRow/name/ATTR/help/description}" visible="{ui>/bShowHelp}"/>
</footer>
</Column>
I change the value of bShowHelp showing and hiding all help infos

Related

SAP UI5 : Unable to bind a controller variable in xml

Button on click of which the variable is getting changed:
<f:content>
<Button icon="sap-icon://edit" press="editClick" type="Transparent"></Button>
</f:content>
xml code where i need 2-way binding:
<VBox class="sapUiSmallMargin">
<form:SimpleForm id="SimpleFormDisplayColumn_oneGroup">
<form:content>
<Label text="{i18n>contextofusage}"/>
<Text text="{contextofusagetext}" visible="{!isInfoEditable}"/>
<Input type="Text" visible="{isInfoEditable}" value="{contextofusagetext}"></Input>
</form:content>
</form:SimpleForm>
</VBox>
controller:
var isInfoEditable=false;
return Controller.extend("abc.controller.Detail", {
editInfoClick: function(event){
if(isInfoEditable){
isInfoEditable=false;
}
else{
isInfoEditable=true;
}
}
});
It seems like you have tried nothing, but I will try to guide you:
You cannot simply declare a variable in your controller and then use it in your view. That's not how UI5 works. Instead create a model and bind it to your view. I also give my models a name, in this case "view":
onInit: function() {
var oViewModel = new sap.ui.model.json.JSONModel({
isInfoEditable: false
});
this.getView().setModel(oViewModel, "view");
}
Then use it in your view. Make sure that you use the name of your model ("view") in your bindings. If you want to do more than simply use the raw value (e.g. negate it) you have to use expression binding. Also you have to use an absolute path starting with /:
<form:SimpleForm id="SimpleFormDisplayColumn_oneGroup">
<form:content>
<Label text="{i18n>contextofusage}"/>
<Text text="{contextofusagetext}" visible="{= !${view>/isInfoEditable} }"/>
<Input type="Text" visible="{view>/isInfoEditable}" value="{contextofusagetext}"></Input>
</form:content>
</form:SimpleForm>
When you click on the button you have to modify/toggle the value in your model:
editClick: function (oEvent) {
var oViewModel = this.getView().getModel("view");
var bIsEditable = oViewModel.getProperty("/isInfoEditable");
// negate the current value and set it as the new value
oViewModel.setProperty("/isInfoEditable", !bIsEditable);
}
I suggest strongly reading on the basics of UI5. Your approach looks more like Vue.js, but UI5 has its own paradigms.

Input assisted doesn't show all suggestions

I have input field i need suggest items from odata model.
<Input
id="productInput"
type="Text"
placeholder="Enter Product ..."
showSuggestion="true"
showValueHelp="true"
valueHelpRequest="handleValueHelp"
suggestionItems="{/ProductCollection}" >
<suggestionItems>
<core:Item text="{Name}" />
</suggestionItems>
</Input>
the problem is there are missing items : not all items are displayed (you can check this link
https://sapui5.hana.ondemand.com/#/sample/sap.m.sample.InputAssisted/preview
it is the same behaviour when you put a for example it shows some items in the search it shows more with a )
What you are trying to do is basically show all items that contains the value in the input. SAPUI5 has a convenient filter for this called sap.ui.model.FilterOperator.Contains.
The problem with the sap.m.Input is that it will only work one way, even if you manually set the Contains filter in the Suggest event, it will show suggestions that will start with the provided letter instead, just like sap.ui.model.FilterOperator.StartsWith filter operator. That's why it is showing you less suggestions.
Using the same products.json model in your question, we can do the following:
XML Input:
<Label text="Product" labelFor="productInput"/>
<Input
id="productInput"
type="Text"
placeholder="Enter Product ..."
showSuggestion="true"
showValueHelp="false"
suggest="handleSuggest"
suggestionItems="{productsModel>/ProductCollection}" >
<suggestionItems>
<core:Item text="{productsModel>Name}" />
</suggestionItems>
</Input>
Controller:
handleSuggest: function (oEvent) {
var aFilters = [];
var sTerm = oEvent.getParameter("suggestValue");
if (sTerm) {
aFilters.push(new sap.ui.model.Filter("Name", sap.ui.model.FilterOperator.Contains, sTerm));
}
oEvent.getSource().getBinding("suggestionItems").filter(aFilters);
//do not filter the provided suggestions before showing them to the user - important
oEvent.getSource().setFilterSuggests(false);
}
It is very important to set the setFilterSuggests() method to false in order not to filter the provided suggestions before showing them to the user, this would go against we just did previously.
Using this approach, the suggested item will show only those values filtered by the specified filter condition which is sap.ui.model.FilterOperator.Contains.
Other SAPUI5 Filter Operators

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.

How to access TextArea's text and/or change it?

XML View
<TextArea id="message"
maxLength="100"
width="100%"
valueLiveUpdate="true"
showExceededText="false"
placeholder="Type here.."
required="true"
/>
Controller
onInit: function() {
// ...
this.getView().byId("message").setText("");
},
Here I tried two commands to clear the text area values. But got error
this.getView().byId("message").setText("");
TypeError: this.getView(...).byId(...).setText is not a function
sap.ui.getCore().byId("message").setText("");
TypeError: sap.ui.getCore(...).byId(...) is undefined.
How to clear TextArea values from JS?
The control sap.m.TextArea doesn't have the text property and thus no such mutator and accessor either. Instead, the text value can be set via the property value since the control extends InputBase.
Therefore, the line should be:
this.byId("message").setValue();

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();
}