【问题标题】:How to bind a list to a navigation property如何将列表绑定到导航属性
【发布时间】:2015-09-16 20:00:58
【问题描述】:

我有一个目录和文件的主/详细应用程序。在我的 OData 服务中,我有一个导航属性,可以从一个目录指向一组文件。我在目录文件的详细视图中有一个列表。但我无法将其绑定到 OData 服务的导航属性

<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>

项目路径是源实体集名称。不知道我应该在哪里得到这个名字。 FileSet 部分来自导航属性。我很困惑如何在视图中映射它。

编辑:我已从 List 标记中删除“item = { }”并尝试将其绑定到 Detail.js 文件中。

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;
        }
    }
});

我已将绑定代码添加到“onRouteMatched”方法中。

编辑 2:

我在控制器中的绑定:

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

我没有返回任何数据,但 SAPUI5 调试器中的路径是正确的,尽管被标记为“无效”

编辑 3

我在 onRouteMatched 函数中使用此代码使其工作

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

【问题讨论】:

    标签: odata sapui5 sap-fiori


    【解决方案1】:

    我认为您缺少的只是在详细视图上设置绑定上下文(也许您还没有看到控制器代码)。
    假设您有 2 个实体文件夹和文件。您的文件夹有一个导航属性 FileSet to Files。
    现在您将文件夹实体绑定到主实体。但是,当您单击 Master 时,详细信息应加载 A 文件夹 的文件,因此您将详细信息视图绑定到 master 中的选定条目。 您如何在主视图中获取所选条目?
    在 Master 上的事件处理程序中,您可以调用

    this.getBindingContext().getPath() 
    

    并将其传递给详细视图。详细可以来电

    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.
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回复。我试过你的建议,但没有奏效。我将编辑帖子并添加 Detail.js 文件
    • 您仍然只绑定了主实体,但没有绑定密钥。因此,可以说 Entity 是 Folders ,其中一个的键是 Folder1 。您需要将详细视图绑定为 Folder('Folder1')。因为 FileSet 需要一个可以运行导航的值。也传递绑定路径。可能 jsbin 或主控制器/视图代码会有所帮助。
    • 如果我在其上设置断点,则 sEntityPath 的值是具有键的实体。但是当我查看 SAPUI5 调试器时,它不会显示列表的绑定
    【解决方案2】:

    您正在绑定到命名模型,但没有在代码中引用“命名”模型。

    即在你的代码中你有

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

    但在您的控制器中,您的代码都没有引用此模型

    例如

    this.getView().getModel()
    

    您应该指定模型的名称(因为您可以有多个模型并且您似乎绑定到一个命名模型。 如果您最初将相关模型命名为 DirectorySet,请在相关操作中指定 - 例如:

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

    我还没有完成所有代码,但这将是一个好的开始。

    编辑: 使用以下方法获取 ACTUAL 值:

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

    只是想确保我们得到完整且正确的绑定路径。

    【讨论】:

    • 感谢您的回复。我已经从视图中删除了路径,现在正在尝试在控制器中实现绑定。我将编辑帖子以显示我当前的绑定。
    • sEntityPath 的值是多少?您能否(如果您还没有)通过使用我在上面编辑我的答案中的建议来查看浏览器控制台中的实际值。
    • 我能够使用 .bindItems 将列表绑定到 sEntityPath。我将发布编辑
    猜你喜欢
    • 2023-04-07
    • 2023-01-05
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 2012-10-08
    相关资源
    最近更新 更多