问题
I have problems with data binding of my custom control.
My control inherits from sap.m.Input
and extends it with a special value helper.
One of my new properties of my new control is a simple header for the value help dialog. This is bound to an i18n model.
When I now use my control in a normal form, everything works. The title is bound correctly and shows the value of the bound i18n property in that model. If I use my control as a template in a column of a sap.ui.table
control, it only shows the default value of the title property. Data binding does not seem to work. But is still working on the inherited properties (such as value).
For simplification here my control which now has only that title property and if valuehelp is requested, it shows the current value in an alert box. In table, it shows the default value. And without table, it shows the bound value from i18n model.
Here the simplified control code:
sap.ui.define([
"sap/ui/core/Control",
"sap/m/Input",
], function(Control, Input) {
"use strict";
return Input.extend("DvpClsSuggestInput", {
"metadata": {
"properties": {
// Title of Value-Help Dialog
"vhTitle": {
type: "string",
defaultValue: "Title"
}
}
},
init: function() {
Input.prototype.init.call(this);
this.setShowValueHelp(true);
this.attachValueHelpRequest(this.onValueHelpRequest.bind(this));
},
onValueHelpRequest: function(oEvent) {
var lvTitle = this.getVhTitle();
alert(lvTitle);
},
});
});
});
Usage in sap.ui.table.Table
(which doesn't work and shows the default value of the title property):
<table:Column>
<m:Label text="{i18gn>HausWaehrung}" />
<table:template>
<dvp:MyInput
value="{ path : 'Inv>Hwaer', type : 'sap.ui.model.type.String' }"
vhTitle="{i18n>Currency}" />
</table:template>
</table:column>
Usage which works:
<VBox>
<dvp:MyInput
value="{
path: 'Cls>/Currency',
type: 'sap.ui.model.type.String'
}"
vhTitle="{i18n>Currency}" />
</VBox>
Once again, binding against the value property works in both ways. Problem only exists with my own property vhTitle
. Any Ideas are welcome.
回答1:
Here is a working example: https://embed.plnkr.co/Va7C1BpyiV1jEV87
In general: the listener object should be passed always as an argument instead of using bind
:
this.attachValueHelpRequest(this.onValueHelpRequest.bind(this), this);
In our case: the listener can be omitted completely:
this.attachValueHelpRequest(this.onValueHelpRequest);
The framework will then pass the current event provider (control instance) as the listener object as described in the API reference:
If <oListener> is not specified, the handler function is called in the context of the event provider. (source)
Why .bind(this)
doesn't work sometimes
If the control is provided as a template control (e.g. in <table:template>
as shown in the question), UI5 clones that template using the clone
API in which all the registered event handlers are also taken into account (code).
When the event handler was registered in init
, the thisArg in this.onValueHelpRequest.bind(thisArg)
was the template control, not the clone instance which has all the bindings.
To make things worse, bind
won't let you change the previously passed thisArg even if the framework tries to call the function afterwards with a different thisArg according to the spec (see Note 2).
This leads to getting the old values from the template rather than the actual values from the rendered clones.
来源:https://stackoverflow.com/questions/61589257/ui5-custom-control-data-binding-not-working-when-used-in-a-table