How to set visible property as false if model does not yet defined? (SAPUI5) - sapui5

my model "categories" is defined on the second view controller and set as a global model. but in the first view, I have a button and set its visible condition like below
<Button text="Click Me" visible="{=${categories>/}.length > 0}" />
the button should only be visible when the categories model has data.
but since I have not yet navigated to the second view and my model is not yet defined. the expression binding is not working for the button in the first view. how do set the button visible as false if the model is not defined and has no data? only using XML, not with javascript.
/}.length > 0}" />

According the Expression Binding Documentation, you can use Function call and Binary logical operator.
With that, you can for example do this expression binding:
{= Array.isArray(${model}) && ${model}.length > 0 }
Check model exists and is an Array
And
Check model size > 0
With that if model is not existent or is not an array or is an empty array the answer is false otherwise true.
With you code it would give :
<Button text="Click Me" visible="{= Array.isArray(${categories>/}) && ${categories>/}.length > 0 }" />
& character from binary operator must be escaped in XML with &
XML syntax escaping rules

Related

How to synchronize control values within different views

I would like to know how to get the content of TextArea, assign the value to a variable, set it to a model, and then set the variable to another TextArea in another view. I have coded some examples and it works, but not on TextArea.
Here is the example code:
// In init of the Component.js
this.setModel(new JSONModel(), "TransportModel"); // JSONModel required from "sap/ui/model/json/JSONModel"
// In *.controller.js
this.getView().getModel("TransportModel").setProperty("/", {
"Serial": this.byId("mat_serial").getValue() // "mat_serial" == id of the Input box in XML view
});
In the last step, I set the Text from a different View (also XML and Input Box) with the Value of the Model Element.
<Text text="{TransportModel>/Serial}" />
That worked pretty well.
But how to do the same with the TextArea? How can I do it based on this model? The value that I want to use from the first TextArea should also be on a TextArea in another view.
UI5 supports two-way data binding. I.e. if the user changes something in the UI (e.g. user types something in the text area), that change will be reflected automatically in other bindings that listen to the change.
<!-- In view 1 -->
<TextArea value="{TransportModel>/Serial}" />
<!-- In view 2 -->
<Text text="{TransportModel>/Serial}" />
No need to get input values by hand. Simply let the framework synchronize the value.
How to use a local json model:
Create
initItemViewModel: function () {
return new JSONModel({
Serial: ""
});
}
this._oViewModel = this.initItemViewModel();
this.setModel(this._oViewModel, "TransportModel");
Using
this.getView().getModel("TransportModel").setProperty("/Serial", serial);
<Text text="{TransportModel>/Serial}" width="auto" maxLines="1"/>

Event Handler for JSONModel Change?

Say, there's an sap.m.table whose items are bound to a JSON model - "/rows". Outside sap.m.table layout, there's a toolbar that contains "Add" button to add rows to the table. "Add" button adds rows to the table using model's setProperty method. Now, the requirement is to disable "Add" button when JSON model "/rows" length has reached 10. How do we create a handler to observe the changes of JSON model's "/rows" property? https://sapui5.netweaver.ondemand.com/1.52.22/#/api/sap.ui.model.Model/events/propertyChange states that
Currently the event is only fired with reason sap.ui.model.ChangeReason.Binding which is fired when two way changes occur to a value of a property binding.
This means that the eventHandler of propertyChange doesn't get triggered when JSONModel's setProperty() is called. Is there a way out where we can observe the changes of JSONModel's property changes - in this case, "/rows" property of the JSONModel?
Well I can think of several ways to achieve this
1. Standard view binding + formatter:
View
...
<Button text="Add" press="onPressAdd" enabled="{path: '/rows', formatter: '.isAddEnabled'}" />
...
Controller:
Controller.prototype.isAddEnabled = function(rows) {
return rows && rows.length < 10;
}
2. Expression binding (pure xml)
...
<Button text="Add" press="onPressAdd" enabled="{= ${/rows/length} < 10 }" />
...
3. JSONPropertyBinding (pure javascript)
You can call bindProperty on JSONModel to create a property binding that can be observed for changes:
https://sapui5.hana.ondemand.com/#/api/sap.ui.model.Model/methods/bindProperty
https://sapui5.hana.ondemand.com/#/api/sap.ui.model.json.JSONPropertyBinding
Controller.prototype.onInit = function() {
var model = this.getMyJsonModel();
var button = this.getView().byId("myButtonId");
model.bindProperty("/rows").attachChange(function(event) {
button.setEnabled(event.getSource().getValue().length < 10);
})
}

Combobox in sap.ui.table.Table

I want to set values in a Combobox in the table: It does not show me the values ? Here is the code:
View:
<Column width="10rem">
<m:Label text="{i18n>Status}" />
<template>
<m:ComboBox items="{items>/Status}"
templateShareable="true">
<m:items>
<core:Item text="{Name}" />
</m:items>
</m:ComboBox>
</template>
</Column>
Controller: This is the parameterset.
success : function(oData, oResponse) {
// create JSON model
var oODataJSONModel = new sap.ui.model.json.JSONModel();
var child1 = [];
child1.push({Name:"S"});
child1.push({Name:"E"});
oData.Status = child1;
oODataJSONModel.setData(oData);
oView.setModel(oODataJSONModel, "items");
Thanks for helping!
You're missing alias for model in property binding of Item.
<core:Item text="{items>Name}" />
If you want to read the value of the combobox when it changes you can do the following. First in the XML, set the property selectionChange="nameOfYourFunction" in the combobox element. Whenever the user clicks on a different item, nameOfYourFunction() will execute. Here in this function you can check for the value.
nameOfYourFunction : function(){
//Do whatever you want to do here when user changes value of combo
this.getView().byId("combobox_id_here").getValue(); // returns text inside combobox
}
You might have to play around with the function and see when exactly it gets called. I have done a little with it and sometimes it gets called twice. I think once when the Combobox's text is a value in the list and then it gets called again when you leave focus of the combobox. Getting called twice probably won't affect your code though, depends on what you do in your function.

Change button class conditionally based on OData Model

I have a basket, each line containing a button with a tooltip which displays if any internal or Supplier Notes haves been entered.
Here's the view code:
<Button text="" icon="sap-icon://notes" tooltip=" {i18n>ReviewBasket.SupplierNote}: {basket>SupplierNote} {i18n>ReviewBasket.InternalNote}: {basket>InternalNote}" press="openSupplierNote"/>​
This is great, but I want to change the type of the button to Emphasized if either internal or supplier notes exist.
I've so far logged the model data, which contains all the info.
OData: Object
items: Array[1]
0: Object
SupplierNote: "Test1
InternalNote: "Test2"
Any suggestions?
You can set the button type with an expression binding.
<Button
icon="sap-icon://notes"
type="{= (${basket>InternalNote} === '' && ${basket>SupplierNote}) ? 'Accept' : 'Emphasized'}"
press="openSupplierNote"/>

ASPxGridView: How to disable GridViewDataColumn when a GridViewDataCheckColumn is checked or unchecked?

I have an ASPxGridView with the following columns:
<dx:GridViewDataCheckColumn FieldName="ProtocolEnabled" Caption="Protocol Enabled">
<DataItemTemplate>
<asp:Literal ID="ltProtocolEnabled" runat="server" />
</DataItemTemplate>
</dx:GridViewDataCheckColumn>
<dx:GridViewDataColumn FieldName="ProtocolCount" Width="0" Caption="Protocol Count">
The checkbox column has a template with a literal in it so I can display Yes/No instead of an empty checkbox, but that's probably TMI. What I need to do is this:
In edit mode: When ProtocolEnabled is checked, I need to enable the ProtocolCount textbox. When ProtocolEnabled is unchecked, I need to disable ProtocolCount and set its text to 0.
I am not asking for a step-by-step, but a general pointer in the right direction. I would like to use callbacks if at all possible. I also promise I will not delete this question as you are answering it =P.
Update: Thanks to answerer, I was sent in the direction I needed to go. Here's the code I used:
<dx:GridViewDataCheckColumn FieldName="ProtocolEnabled" Caption="Protocol Enabled" CellStyle-HorizontalAlign="Left">
<DataItemTemplate>
<asp:Literal ID="ltProtocolEnabled" runat="server" />
</DataItemTemplate>
<PropertiesCheckEdit>
<ClientSideEvents CheckedChanged="function(s,e) {ProtocolEnabledChecked(s);}" />
</PropertiesCheckEdit>
</dx:GridViewDataCheckColumn>
<dx:GridViewDataColumn FieldName="ProtocolCount" Width="0" Caption="Protocol Count">
function ProtocolEnabledChecked(ck) {
var x = gvApplicationServer.GetEditor("ProtocolCount");
if (ck.GetValue()) {
x.enabled = true;
}
else {
x.SetValue(0);
x.enabled = false;
}
}
It's clientside code instead of callback.
First of all Check this for Accessing Controls Contained within Templates
To show Yes/No
On HtmlRowCreated Event access control and set it's text property after finding the control in the
Literal literal = ASPxGridView1.FindRowCellTemplateControl(e.VisibleIndex,
ASPxGridView1.Columns["Name"] as GridViewDataColumn, "ASPxButtonEdit1") as Literal ;
literal.Text = (bool)grid.GetRowValues(e.VisibleIndex, "columnName") ? "Yes" : "No";
In Edit Row Template Do as you did as above..
If you want to do some client side functionality then .. create client side event OnClientClick and use checkbox client side method. chkclientinstanceName.getValue(); or other to check with it is checked or not..
these controls are client accessible so enable/ disable by using txtClientName.SetEnabled(true/false);
for more help go to the
DevExpress.Web.ASPxEditors ClientScript namespace..
Try this step by step .. hope it will be helpful..