chiranjeevigk
chiranjeevigk

Reputation: 1676

Bindings not updated after array size change in UI5

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?

Upvotes: 2

Views: 2968

Answers (2)

Boghyon Hoffmann
Boghyon Hoffmann

Reputation: 18064

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.

Upvotes: 2

Qualiture
Qualiture

Reputation: 4920

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

Upvotes: 1

Related Questions