0
votes

I have a master/detail application for directories and files. In my OData service i have a navigation property that leads from a directory to a set of files. I have a list in the detail view for the files of the directory. But i am having trouble binding it to the navigation property of the OData service

<mvc:View xmlns:core="sap.ui.core" xmlns:f="sap.ui.layout.form" xmlns:l="sap.ui.layout" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="FileUtility.view.Detail">
    <Page id="detailPage" navButtonPress="onNavBack" showNavButton="{device&gt;/isPhone}" title="Files">
        <content>
            <ObjectHeader iconActive="false" id="detailHeader" introActive="false" number="" numberUnit="" title="" titleActive="false">
                <attributes id="detailAttributes">
                    <ObjectAttribute active="false" id="attribute" text="{i18n&gt;detailText}"/>
                </attributes>
                <firstStatus id="detailStatus">
                    <ObjectStatus id="status" text=""/>
                </firstStatus>
            </ObjectHeader>
            <List id="__list0" noDataText="Drop list items here" items="{path :'DirectorySet>/FileSet'}">
                <items>
                <ObjectListItem counter="0" id="__item5" showMarkers="false" title="{Name}" type="Active">
                </ObjectListItem>
                </items>
                <core:ExtensionPoint name="extDetail"/>
            </List>
        </content>
        <footer id="detailFooter">
            <Toolbar id="detailToolbar">
                <content>
                    <ToolbarSpacer id="toolbarSpacer"/>
                    <Button icon="sap-icon://action" id="actionButton" press="openActionSheet"/>
                </content>
            </Toolbar>
        </footer>
    </Page>
</mvc:View>

The items path is the source entity set name. Not sure where im supposed to get this name. The FileSet portion is from the navigation property. I am confused as how to map it in the view.

EDIT: i have removed the "item = { }" from the List tag and tried to bind it in the Detail.js file.

sap.ui.core.mvc.Controller.extend("FileUtility.view.Detail", {

    onInit : function() {
        this.oInitialLoadFinishedDeferred = jQuery.Deferred();

        if(sap.ui.Device.system.phone) {
            //Do not wait for the master when in mobile phone resolution
            this.oInitialLoadFinishedDeferred.resolve();
        } else {
            this.getView().setBusy(true);
            var oEventBus = this.getEventBus(); 
            oEventBus.subscribe("Component", "MetadataFailed", this.onMetadataFailed, this);
            oEventBus.subscribe("Master", "InitialLoadFinished", this.onMasterLoaded, this);
        }

        this.getRouter().attachRouteMatched(this.onRouteMatched, this);
    },

    onMasterLoaded :  function (sChannel, sEvent) {
        this.getView().setBusy(false);
        this.oInitialLoadFinishedDeferred.resolve();
    },

    onMetadataFailed : function(){
        this.getView().setBusy(false);
        this.oInitialLoadFinishedDeferred.resolve();
        this.showEmptyView();       
    },

    onRouteMatched : function(oEvent) {
        var oParameters = oEvent.getParameters();
        var oView = this.getView();
        var sEntityPath = "/" + oParameters.arguments.entity;

        var oContext = new sap.ui.model.Binding(this.getView().getModel(), sEntityPath + '/FileSet');
        this.getView().setBindingContext(oContext);
        //var oList = oView.byId("__list0");
        //oList.bindItems(sEntityPath + '/FileSet',sap.ui.getCore().byId(this.getView().byId('__item5').getId()));
        //sap.ui.getCore().byId(this.getView().byId('__list0').getId()).bindItems(sEntityPath + '/FileSet',sap.ui.getCore().byId(this.getView().byId('__item5').getId()));

        //this.bindView(sEntityPath);

        jQuery.when(this.oInitialLoadFinishedDeferred).then(jQuery.proxy(function () {


            // When navigating in the Detail page, update the binding context 
            if (oParameters.name !== "detail") { 
                return;
            }




            var oIconTabBar = oView.byId("idIconTabBar");
            oIconTabBar.getItems().forEach(function(oItem) {
                if(oItem.getKey() !== "selfInfo"){
                    oItem.bindElement(oItem.getKey());
                }
            });

            //var oList = oView.byId("__list0");
            //oList.bindItems(sEntityPath + '/FileSet');
            //sap.ui.getCore().byId(this.getView().byId('__list0').getId()).bindItems(sEntityPath + '/FileSet',sap.ui.getCore().byId(this.getView().byId('__item0').getId()));

            // Specify the tab being focused
            var sTabKey = oParameters.arguments.tab;
            this.getEventBus().publish("Detail", "TabChanged", { sTabKey : sTabKey });

            if (oIconTabBar.getSelectedKey() !== sTabKey) {
                oIconTabBar.setSelectedKey(sTabKey);
            }
        }, this));

    },

    bindView : function (sEntityPath) {
        var oView = this.getView();
        oView.bindElement(sEntityPath); 

        //Check if the data is already on the client
        if(!oView.getModel().getData(sEntityPath)) {

            // Check that the entity specified was found.
            oView.getElementBinding().attachEventOnce("dataReceived", jQuery.proxy(function() {
                var oData = oView.getModel().getData(sEntityPath);
                if (!oData) {
                    this.showEmptyView();
                    this.fireDetailNotFound();
                } else {
                    this.fireDetailChanged(sEntityPath);
                }
            }, this));

        } else {
            this.fireDetailChanged(sEntityPath);
        }

    },

    showEmptyView : function () {
        this.getRouter().myNavToWithoutHash({ 
            currentView : this.getView(),
            targetViewName : "FileUtility.view.NotFound",
            targetViewType : "XML"
        });
    },

    fireDetailChanged : function (sEntityPath) {
        this.getEventBus().publish("Detail", "Changed", { sEntityPath : sEntityPath });
    },

    fireDetailNotFound : function () {
        this.getEventBus().publish("Detail", "NotFound");
    },

    onNavBack : function() {
        // This is only relevant when running on phone devices
        this.getRouter().myNavBack("main");
    },

    onDetailSelect : function(oEvent) {
        sap.ui.core.UIComponent.getRouterFor(this).navTo("detail",{
            entity : oEvent.getSource().getBindingContext().getPath().slice(1),
            tab: oEvent.getParameter("selectedKey")
        }, true);
    },

    openActionSheet: function() {

        if (!this._oActionSheet) {
            this._oActionSheet = new sap.m.ActionSheet({
                buttons: new sap.ushell.ui.footerbar.AddBookmarkButton()
            });
            this._oActionSheet.setShowCancelButton(true);
            this._oActionSheet.setPlacement(sap.m.PlacementType.Top);
        }

        this._oActionSheet.openBy(this.getView().byId("actionButton"));
    },

    getEventBus : function () {
        return sap.ui.getCore().getEventBus();
    },

    getRouter : function () {
        return sap.ui.core.UIComponent.getRouterFor(this);
    },

    onExit : function(oEvent){
        var oEventBus = this.getEventBus();
        oEventBus.unsubscribe("Master", "InitialLoadFinished", this.onMasterLoaded, this);
        oEventBus.unsubscribe("Component", "MetadataFailed", this.onMetadataFailed, this);
        if (this._oActionSheet) {
            this._oActionSheet.destroy();
            this._oActionSheet = null;
        }
    }
});

I have added the binding code to the "onRouteMatched" method.

EDIT 2:

My binding in the controller:

var oList = oView.byId("__list0");
var oTemplate = this.getView().byId('__item5');
oList.bindItems(sEntityPath + '/FileSet',sap.ui.getCore().byId(oTemplate.getId()));

I am not getting any data back but the path in the SAPUI5 debugger is correct despite being marked as "invalid"

EDIT 3

I got it working using this code in the onRouteMatched function

var oList = oView.byId("__list0");
var oTemplate = oView.byId('__item5');
oTemplate.bindProperty('title', 'Name');
oList.bindItems(sEntityPath + '/FileSet', sap.ui.getCore().byId(oTemplate.getId()));
2

2 Answers

1
votes

I think what you are missing is just setting the binding context on the detail view(Maybe you have have not seen the controller code).
Lets say you have 2 entities Folders and Files. Your Folders has a navigation property FileSet to Files.
Now you have Folders entity bound to the Master entity. But when you click on the Master and detail should load the files of A Folder so then you will have bind the detail view to the selected entry in master. How can you get the selected entry in Master view??
In the event handler on action on Master you can call

this.getBindingContext().getPath() 

and pass this over to the detail view. In the detail you can call

var oContext = new sap.ui.model.Binding(oModel,sPath)
//sPath is the path from master view , oModel is the oData model of your application
this.getView().setModel(oModel);
this.getView().setBindingContext(oContext);
//Now the FileSet of your list will fire and load the data in your list.

Hope this helps.

1
votes

You are binding to a named model but are not referencing the "named" model in your code.

i.e. in your code you have

="{path :'DirectorySet>/FileSet'}">

yet in your controller none of your code references this model

e.g.

this.getView().getModel()

you should specify the name of the model (as you can have several models AND you appear to be binding to a named model. If you initially named the model in question DirectorySet then specify that in the relevant operations - e.g.:

this.getView().getModel("DirectorySet")

I haven't been through all the code but this would be a good start.

EDIT: Use the following to get the ACTUAL values:

jQuery.sap.log.setLevel(jQuery.sap.log.LogLevel['INFO']);
jQuery.sap.log.info("fully qualified path: " + sEntityPath + '/FileSet',sap.ui.getCore().byId(oTemplate.getId()));

Just want to be sure we are getting the full and correct binding path.