2
votes

Main.view.xml:

<ObjectHeader
    id="objectHeader"
    title="{name}"
    intro="{id}">
    <headerContainer>
        <IconTabBar
            id="tabBar"
            items="{
                path: 'assigned',
                parameters: {expand: 'b, c'} 
            }"
            select="onTabBarSelect">
        </IconTabBar>       
    </headerContainer>
</ObjectHeader>

Main.controller.js

onMasterSelectionChange : function (sPath) {
    var oSource = oEvent.getParameter("listItem") || oEvent.getSource(),
    // sPath = "/ASet('d')"
    sPath = oSource.getBindingContext().getPath(),
    oObjectHeader = this.byId("objectHeader");

    oObjectHeader.bindElement(sPath);
    this._oModel.attachEventOnce("requestCompleted", function(oEvent) {
        var oTabBar =  this.byId("TabBar");
        oFirstListItem = oTabBar.getItems()[0],
        sObjectId = oFirstListItem.getBindingContext().getProperty("id"),
        sDPath = "/DSet('" + sObjectId + "')";

        this._getControls(sDPath);
    }, this);
}

I found a strange behavior: when I change the master list selection, sometimes Network will show a "/ASet/assigned" call, but sometimes there will be no call, which cause requestCompleted not fired.

According to: SAPUI5 - bindElement doesn't work the second time,

If you call bindElement with the same path twice, the second time won't actually trigger a new call to get new data, since the path didn't change.

But I am sure it is different path. Is there any way that can trigger this call?


BTW

oObjectHeader.bindElement({
    path : sPath,
    events: {
        change : function (oData, test) {
        },
        dataRequested : function (oData) {
        },
        dataReceived: function (oData) {
        }
    }
});

change can be fired every time I click master list, but dataRequested and dataReceived is never called.

4
Set a breakpoint at ODataContextBinding.prototype.initialize and see what's happening there (especially at bReloadNeeded )Boghyon Hoffmann
Can you show us how your app is structured and how bindings are done (in addition to the ObjectHeader)? Are you binding a collection to your master with expand to the "detail"s? In that case, it would make sense that no requests are sent afterwards because the data is already cached whatever you select.Boghyon Hoffmann
Sorry, how to get ODataContextBinding ? And yes, it is a master-detail with expand. My aim is load the first master list item, and activate the first icon tab bar when page opens.Tina Chen

4 Answers

2
votes

I know this is an old post but you can actually trigger a network call for the bindElement by refreshing the binding within its change event.

this.getView().bindElement({
    path: "model>/" + sContextPath,
    events: {
        change: function (oEvent) {
            // Get the context binding object
            var oContextBinding = oEvent.getSource();

            // Refresh the binding.
            // This triggers a network call.
            oContextBinding.refresh(false);
        }.bind(this)
    }
});

Refreshing the binding, triggers the network call. Also, set the bForceUpdate flag of the refresh to false so that it would only update the UI if there is a change in the data as mentioned in the APIs.

1
votes

If your ODataModel has already loaded the data under sPath (check in myODataModel.oData) it will not load that data again. Therefore dataRequested/dataReceived will not fire.

But change should fire whenever the path changes no matter if data existed or not.

0
votes

I find a work around by replace bindElement by change&oModel.read ...

onMasterSelectionChange : function (sPath) {
    var oSource = oEvent.getParameter("listItem") || oEvent.getSource(),
    // sPath = "/ASet('d')"
    sPath = oSource.getBindingContext().getPath(),
    oObjectHeader = this.byId("objectHeader");

    oObjectHeader.bindElement({
        path : sPath,
        events: {
            change : this._onBindingChange.bind(this, sPath)
        }
    })
},

_onBindingChange : function(sPath) {
    this._oModel.read(sPath + "/assigned", {
        urlParameters: {
            "$expand": "b, c"
        },
        success: function(oData) {
            var aAssigmentSet = oData.results,
            oViewModel = this.getModel("viewModel"),
            oTabBar =  this.byId("hazardTabBar");

            oViewModel.setProperty("/aAssigmentSet", aAssigmentSet);
            oTabBar.bindAggregation("items",
                "viewModel>/aAssigmentSet",
                new sap.m.IconTabFilter({
                    key: "{viewModel>id}",
                    tooltip : "{viewModel>id}",
                    text : {
                        parts: [{path: "viewModel>b/name"},
                        {path: "viewModel>c/type"}],
                        formatter : function(name, type) {
                            var sType = type.split(".");
                            return name + " (" + sType[sType.length - 1] + ")"; 
                        }
                    }
                })
            );

            if (oTabBar.getItems().length > 0) {
                var sSelectedTabKey;
                    sSelectedTabKey = oTabBar.getItems()[0].getKey();
                    oTabBar.fireSelect({selectedKey: sSelectedTabKey});
            }
        }.bind(this),
        error: this.errorCallback.bind(this)
    });
},

onTabBarSelect : function(oEvent) {
    var sRiskAssignmentPath = "/AssignmentSet('" + oEvent.getParameter("selectedKey") + "')";

    this._oModel.read(AssignmentSet + "/assignedAssignedControls", {
        ...
    }); 
}
0
votes

I think the propper way to achieve this would be to use the invalidate-Method form Odata-Model.

This invalidates all cached entries and forces a new read for the Bindings:

https://sapui5.hana.ondemand.com/#/api/sap.ui.model.odata.v2.ODataModel%23methods/invalidate