3
votes

How can I pass OData value to property of a custom UI5 control? I tried this but it's not working.
If I try passing it to normal control like <Text>, it's working fine.
If I try passing a static value, it's working fine too:

<cc:CheckPrice valuePrice="{Price}"/> <!--❌-->
<Text text="{Price}"/> <!--✔️-->
<cc:CheckPrice valuePrice="1000"/> <!--✔️-->

How can I pass the value from a remote OData service to show it like in Text control?

Screenshot of the rendered custom control

sap.ui.define([
    "sap/ui/core/Control",
    "sap/m/Label",
    "sap/m/Button"
], function (Control, Label, Button) {
    "use strict";

    return Control.extend("zgutfiory.zguttestfiorylr.controls.CheckPrice", {
        metadata: {
            properties: {
                "valuePrice": {
                    type: "string",
                    bindable: "bindable"
                }
            },
            aggregations: {
                "_label": {
                    type: "sap.m.Label",
                    multiple: false,
                    visibility: "hidden"
                },
                "_button": {
                    type: "sap.m.Button",
                    multiple: false,
                    visibility: "hidden"
                }
            },
            events: {
                // ...
            }
        },

        init: function () {
            this.setAggregation("_label", new Label({
                text: "{i18n>controlCheckPrice}"
            }).addStyleClass("sapUiSmallMargin"));
            this.setAggregation("_button", new Button({
                text: "{i18n>controlCheckPrice}",
                press: [this._onSubmit, this]
            }).addStyleClass("sapUiTinyMarginTopBottom"));
        },

        _onSubmit: function (oEvent) {
            // ...
        },

        renderer: function (oRm, oControl) {
            oRm.write('<div class="zgutCheckPriceWrap">');
            oRm.write('<div class="zgutPriceWrap">' + oControl.getValuePrice() + '</div>');
            oRm.renderControl(oControl.getAggregation("_label"));
            oRm.renderControl(oControl.getAggregation("_button"));
            oRm.write('</div>');
        }
    });
});

UI5 version: 1.92

3

3 Answers

2
votes

You missed adding some mandatory control data in the render function. When the model value changes (e.g. ODataModel receiving data), the control with the bound property needs to be identifiable by an id at least so that the control can be updated. In your case, the id was not rendered.

To add the required control data, use:

  • oRm.openStart("div", oCotrol) in case of the new semantic rendering (UI5 ≥ 1.67).
  • oRm.writeControlData(oControl) in case of the now-deprecated string-based rendering (UI5 ≤ 1.66). Note: please use .writeEscaped for oControl.getValuePrice() here to avoid XSS.

Also, make sure to call the super function if you overwrite borrowed methods (e.g. init). This is especially important for lifecycle hooks.

Sample: https://embed.plnkr.co/gnmPoh3KS7L3DDXZ?show=controls%2FCheckPrice.js,preview


See the API reference: sap/ui/core/RenderManager for more information.

1
votes

The binding for custom control is exactly same as standard control. Below points have to be considered:

  • If the parent container e.g. view is bound with a context, you have to provide the relative path of the attribute you are binding the value with e.g. {Price}. Otherwise, give absolute path e.g. {/Price}
  • If the model is named, make sure to provide the name when binding. E.g. {namedModel>/Price}
  • Path can be multi-level as well. E.g. {ToCategory/CategoryName} for OData property binding using NavigationProperty ToCategory
-1
votes

Seems likely that you are maybe just missing the leading slash?

<cc:checkPrice id="checkPrice" valuePrice="{/Price}" class="sapUiSmallMarginBeginEnd" />