2

I need to enable or disable a button based on the bound array size.

<mvc:View
  xmlns="sap.m"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns:core="sap.ui.core"
  height="100%"
  controllerName="test.controller.expbind">
  <Button text="Need to Enable" enabled="{= ${/listOfData}.length > 0 }"/>
  <List headerText="Data" items="{/listOfData}">
    <StandardListItem title="{Name}" />
  </List>
  <Button text="AddSomeData" press=".onPress" />
</mvc:View>
onInit: function() {
  this.viewModel = new JSONModel({
    listOfData: []
  });
  this.getView().setModel(this.viewModel);
},

onPress: function() {
  var existingdata = this.viewModel.getProperty('/listOfData');
  existingdata.push({ Name:"New" });
  this.viewModel.setProperty('/listOfData', existingdata);
},

After adding the data, the "Need to Enable"-button has to be enabled, but its not happening.

Is there ayny issue with my expression binding?

Boghyon Hoffmann
  • 15,517
  • 8
  • 61
  • 146
chiranjeevigk
  • 1,546
  • 1
  • 22
  • 42

2 Answers2

2

Use .concatapi instead.

const myArray = myClientModel.getProperty('/data');
// instead of myArray.push({/*...*/});
const myNewArray = myArray.concat({/*...*/}); // myNewArray !== myArray
myClientModel.setProperty('/data', /*instead of the old reference:*/myNewArray);

.push should be avoided since it manipulates the original array causing side-effects. The real reason why it didn't work in your case, however, was because the reference passed to setProperty was identical to the old reference (internally compared with === within deepEqual()). Hence, UI5 sees no change and doesn't notify any listeners.

model.refresh(true) unnecessarily forces all bindings (incl. aggregation bindings) and all listeners to re-calculate everything.

.concat on the other hand, creates a new reference. UI5 notifies then only those listeners that care about the change.

Boghyon Hoffmann
  • 15,517
  • 8
  • 61
  • 146
1

Since XMLView expression binding is calculated during pre-processing, it's not being recalculated upon updating the model directly.

You can avoid this behavior by using a formatter function, or update the model with a forced refresh of the bindings after you have updated your model:

this.viewModel.refresh(true);
Qualiture
  • 4,860
  • 6
  • 26
  • 37