attachChange callback not fired for getBinding(“te

2019-02-28 15:52发布

onInit(): function{
    this._oSelectedTrainingsModel = new sap.ui.model.json.JSONModel([]);
    this.getView().setModel(this._oSelectedTrainingsModel, "selectedTrainings");
},

onAfterRendering: function() {
    this.getView().byId("ViewSelectionButton").getBinding("text").attachChange(this._onTextUpdated, this);
},

In the XML view I have this binding:

<Button id="ViewSelectionButton"
    class="magnificationPrep"
    icon="sap-icon://cart-full"
    tooltip="Share"
    text="{i18n>viewTrainingsButton} ({= %{selectedTrainings>/}.length })"
    press="handlePressViewSelection"
/>

At some point in the controller, an object is added to the _oSelectedTrainingsModel:

this._oSelectedTrainingsModel.getProperty("/").push(oNewSelection);

At this point, the bound text property is changed and thus I'm expecting a call to the callback function _onTextUpdated.

The model is empty, this is probably part of the issue?

...getBinding("text") object in onAfterRendering()

标签: sapui5
2条回答
等我变得足够好
2楼-- · 2019-02-28 16:45

In order to update the UI via binding, you have to use setProperty with the same path used in the binding definition which triggers checkUpdate (<-- fires change event).

The problem was that you mutated the selectedTrainings-array manually via getProperty(...).push. This bypasses notifying UI5 about the changes since getProperty doesn't trigger checkUpdate. Therefore..:

Instead of

this._oSelectedTrainingsModel.getProperty("/").push(oNewSelection);
this._oSelectedTrainingsModel.refresh(true);

Do

const newArray = this._oSelectedTrainingsModel.getProperty("/").concat(oNewSelection);
this._oSelectedTrainingsModel.setProperty("/", newArray);

This alone is sufficient to update the UI thanks to the one-way data binding:

One-way binding means a binding from the model to the view; value changes in the model update all corresponding bindings and the view (and not the other way around).

There is no need to call refresh(true) which is an indication of anti-pattern. Here is a demo: stackoverflow.com/a/48226884


Btw: the module returned by getBinding("text") is CompositeBinding since there are more than one binding definitions involved. The CompositeBinding however does not offer attachChange for public use. So it shouldn't have been used anyway.

查看更多
一夜七次
3楼-- · 2019-02-28 16:46

I believe change event is not triggered because of the way you have bound your model and Text property of Button.

Due to expression binding, ONE-WAY-BINDING has occured, meaning value will be changed in MODEL only and will not be reflected back in UI. See Image below:

enter image description here

To Solve the problem, I manually triggered an refresh event, which will update all the binding(forcefully) and hence, change event of Button Text was triggered.

So, code:

    this.getView().getModel('newModel').getProperty("/").push({});
    this.getView().getModel('newModel').refresh(true);

where newModel is my named model.

However, while debugging, I found two problems: :(

  1. Why is change event triggered twice after manual refresh ?

  2. Shouldn't onChange() be triggered if I do:

this.byId('btn2').setText('Hey1!!') ? But it wasn't.

I hope it helps you.

查看更多
登录 后发表回答