getOwnerComponent() returns 在按需嵌入视图的控制器中未定义

getOwnerComponent() returns undefined in controller of which view was embedded on-demand

如果满足某些要求,我想将第二个视图嵌套到我的根视图中。通过创建一个 XMLView 对象并将其添加到 <App> 元素的 <page> 聚合中,效果很好。但是当我尝试通过 this.getOwnerComponent().getModel() 访问默认模型(由 manifest.json 文件创建)时,它会抛出:

Uncaught TypeError: Cannot read property 'getModel' of undefined

它在根控制器中工作,但在嵌套控制器中,this.getOwnerComponent() 再次返回 undefined

如果在根视图的开头添加视图,它甚至可以工作。也许我在我的控制器中以错误的方式将它添加到视图中?


RootView.view.xml:

<mvc:View controllerName="test.demo.controller.RootView" xmlns:mvc="sap.ui.core.mvc">
    <App id="app" xmlns="sap.m">
        <Page id="page" title="{i18n>title}">
            <Button text="load nested view" press=".onLoadButtonPress"/>
        </Page>
    </App>
</mvc:View>

RootView.controller.js:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/core/mvc/XMLView"
], function (Controller, XMLView) {
    "use strict";

    return Controller.extend("test.demo.controller.RootView", {
        onLoadButtonPress: function () {
            this.mDefault = this.getOwnerComponent().getModel(); // works just fine
            alert(this.mDefault);
            XMLView.create({
                viewName: "test.demo.view.NestedView"
            }).then(function(oView) {
                this.byId("page").addContent(oView);
            }.bind(this));
        }
    });
});

NestedView.view.xml:

<mvc:View xmlns:mvc="sap.ui.core.mvc" controllerName="test.demo.controller.NestedView">
  <!-- ... -->
</mvc:View>

NestedView.controller.js:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";

    return Controller.extend("test.demo.controller.NestedView", {
        onInit: function () {
            this.mDefault = this.getOwnerComponent().getModel(); // throws Uncaught TypeError: this.getOwnerComponent() is undefined
            alert(this.mDefault);
        }
    });
});

manifest.json 中,我添加了 GWSAMPLE_BASIC OData 服务作为默认模型。

当应用程序代码中的调用者创建 on-demand 视图或 ManagedObject 的任何其他实例时,需要从中访问所有者组件信息,应该在方法 runAsOwner from your target sap.ui.core.Component 中完成.例如:

// XMLView required from "sap/ui/core/mvc/XMLView"
onLoadButtonPress: async function() {
  const fn = () => XMLView.create({ viewName: "test.demo.view.NestedView" });
  const oView = await this.getOwnerComponent().runAsOwner(fn);
  this.byId("page").addContent(oView);
},

示例: https://embed.plnkr.co/29UrnDHpTHquNWuH

根据 API 参考:

Ownership for objects is only checked by the framework at the time when they are created. It is not checked or updated afterwards. And it can only be detected while the Component.runAsOwner function is executing. Without further action, this is only the case while the content of a UIComponent is constructed or when a Router creates a new View and its content. (source)

然后在嵌套视图的控制器中,调用 this.getOwnerComponent() returns 正确分配的组件而不是 undefined,因此 this.getOwnerComponent().getModel() 有效。


提示:加载片段时,优先选择controller API loadFragment over Fragment.load since loadFragment automatically calls Fragment.load with the controller's component.runAsOwner.src