getOwnerComponent() возвращает неопределенное в контроллере, представление которого было внедрено по требованию

#sapui5

#sapui5

Вопрос:

Я хочу вложить второй вид в мой корневой вид, если будут выполнены некоторые требования. Это отлично работает путем создания объекта XMLView и добавления его в <page> агрегацию <App> элемента. Но когда я пытаюсь получить доступ к модели по умолчанию (которая создается manifest.json файлом) через this.getOwnerComponent().getModel() , он выдает:

Неперехваченная ошибка типа: не удается прочитать свойство ‘getModel’ неопределенного

Это сработало в корневом контроллере, но во вложенном контроллере 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 в качестве модели по умолчанию.

Ответ №1:

Когда вызывающий объект в коде приложения создает по требованию представление или любой другой экземпляр managedObject, из которого должна быть доступна информация о компоненте владельца, это должно быть сделано в методе runAsOwner из вашей цели 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:

Владение объектами проверяется фреймворком только во время их создания. Впоследствии оно не проверяется и не обновляется. И это может быть обнаружено только во время выполнения Component.runAsOwner функции. Без дальнейших действий это имеет место только при создании содержимого UIComponent или когда маршрутизатор создает новое представление и его содержимое. (источник)

Затем в контроллере вложенного представления вызов this.getOwnerComponent() возвращает правильно назначенный компонент вместо undefined и, таким образом, this.getOwnerComponent().getModel() работает.


Совет: при загрузке фрагментов отдавайте предпочтение API loadFragment контроллера, Fragment.load поскольку loadFragment он автоматически вызывает Fragment.load компонент контроллера .runAsOwner .src