SAP UI5: проблемы с передачей параметров master-detail

#json #master-detail #sapui5

#json #master-detail #sapui5

Вопрос:

У меня есть некоторые проблемы с передачей параметров с master на страницу detail в SplitApp. Я использую локальный файл JSON, который указан в качестве модели в manifest.json.

Я могу передать идентификатор объекта, но в этом случае я не могу понять, как получить соответствующий элемент в подробном представлении, чтобы привязать его к представлению.

Я также пытался передать путь к элементу, но в этом случае URL-адрес не меняется после выбора элемента списка.

Есть идеи, как я могу отобразить детали на странице сведений?

manifest.json:

 ...
    "models": {
            "items": {
                "type": "sap.ui.model.json.JSONModel",
                "uri": "model/items.json"
            }
        },
    "routing": {
            "config": {
                "controlId": "rootControl",
                "viewPath": "my.try.view",
                "viewType": "XML",
                "async": true
            },
            "routes" : [
                {
                    "pattern" : "",
                    "name" : "master",
                    "target" : ["detail", "master"]
                },
                {
                    "pattern": "detail/{Id}",
                    "name":"detail",
                    "target": ["master", "detail"]
                }
            ],
            "targets" : {
                "master" : {
                "viewName" : "Master",
                "controlAggregation" : "masterPages"
                },
                "detail" : {
                    "viewName" : "Detail",
                    "controlAggregation" : "detailPages"
                }
            }
        }...
  

Master.view.xml

 <mvc:View controllerName="my.try.controller.Master" xmlns:semantic="sap.m.semantic" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m">
    <semantic:MasterPage title="Persons">
                    <List id="idList" items="{items>/item}" selectionChange="onItemPressed" mode="SingleSelectMaster">
                        <items>
                            <ObjectListItem title="{item>Date}">
                                <firstStatus>
                                    <ObjectStatus text="{item>Status}"/>
                                </firstStatus>
                            </ObjectListItem>
                        </items>
                    </List>
        </semantic:MasterPage>
</mvc:View>
  

Master.controller.js

 sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/ui/model/json/JSONModel"
    ], function(Controller, JSONModel) {

        "use strict";

        return Controller.extend("my.try.controller.Master", {

        onInit: function() {
            this.oRouter = this.getOwnerComponent().getRouter();
        },

        onItemPressed: function(oEvent) {
        // When I try with the path, nothing happens. Only passing the Id works!?   
        //  var oItemID = oEvent.getParameter("listItem").getBindingContext("items").getPath().substr(1);
            var oItemID = oEvent.getParameter("listItem").getBindingContext("items").getProperty("Id");
            this.oRouter.navTo("detail", {
            Id: oItemID
            });
        }
        });
    });
  

Detail.view.xml

 <mvc:View controllerName="my.try.controller.Detail" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:semantic="sap.m.semantic">
    <semantic:DetailPage title="Detail">
        <ObjectHeader title="{ItemName}"/>
    </semantic:DetailPage>
</mvc:View>
  

Detail.controller.js

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

            "use strict";

            return Controller.extend("my.try.controller.Detail", {

            onInit: function() {
                this.oRouter = this.getOwnerComponent().getRouter();
                this.oRouter.getRoute("detail").attachPatternMatched(this._onDetailRouteHit, this);
            },

            _onDetailRouteHit: function(oEvent) {

                var sID = oEvent.getParameter("arguments").Id;
//The parameter is passed
                alert(sID);

//This doesn't work. How can I do this withou having a service?
                this.getView().getModel().metadataLoaded().then(function() {
                    var sObjectPath = this.getView().getModel().createKey("ItemSet", {
                        Id : sID
                    });
                    this.getView().bindElement({
                        path: "/"   sObjectPath
                    });
                }.bind(this));
            }   
        });
    });
  

Ответ №1:

Я бы рекомендовал использовать идентификатор вместо пути привязки, поскольку URL-адрес маршрута можно добавлять в закладки. При использовании пути привязки выбранная деталь может измениться при изменении коллекции.

JSONModel не имеет понятия о метаданных или ключах. Итак, вам нужно выполнить поиск элемента в модели и самостоятельно создать путь привязки:

            _onDetailRouteHit: function(oEvent) {

                var sID = oEvent.getParameter("arguments").Id;
//The parameter is passed
                alert(sID);
                var model = this.getView().getModel("items");

                // If you are not shure if the data has been loaded
                // you should create a promise together with the model,
                // fullfill it in the requestCompleted Event and
                // execute the next lines in its then().

                var array = model.getProperty("/ItemSet");
                for(var i = 0, len=array.length; i<len; i  ){
                   if (array[i].Id===sID){
                      this.getView().bindElement({ path: "items>/ItemSet/" i });
                      break;
                   }
                }
            }   
  

Комментарии:

1. Хорошо, спасибо за подсказку! Кажется, что модель не настроена для представления. Я получаю сообщение об ошибке: «Ошибка типа Uncaught (в обещании): не удается прочитать свойство ‘getProperty’ неопределенного. Я думаю, что, определяя модели в дескрипторе, модели должны быть доступны во всем приложении. Я ошибаюсь?

2. Вы инициализируете маршрутизатор после вызова метода базовых классов init() в своих компонентах init() ? Поместите точку останова после вызова base.init() и убедитесь, что модель доступна в компоненте. Представления должны наследовать модели компонента.

3. Ах, я только что узнал, что ваша модель называется items . Вы должны дать имя методу getModel() и указать префикс модели в привязке элемента.

4. Да, верно. Просто узнал это. Спасибо! Итак, теперь все передано, условие находит правильный идентификатор и, следовательно, также правильный индекс. Но привязка, похоже, не работает. По крайней мере, значения не обновляются. Я попробовал с { path: «items>/ItemSet/» i }, { path: «/items>/ItemSet/» i }, { path: «/ItemSet/» i } и в представлении с {ItemName} и {/ItemName} . Когда я пытаюсь протестировать представление с помощью {items>/ItemSet/0/ItemName}, это работает. Где я пропускаю шаг?

5. Правильно! Название модели должно быть указано на каждой привязке. это связано с тем, что вы можете выбирать из всех доступных моделей в каждой привязке. Здорово, что вы это поняли!

Ответ №2:

Попробуйте установить модель глобально в Component.js , контекст привязки может отсутствовать или маршрут не соответствует, взгляните на это приложение, показывающее, как перемещаться между основными и двойными подробными представлениями Мастер-Подробный пример

manifest.json

             "routes": [{
            "name": "master",
            "pattern": "",
            "target": ["master"]
        }, {
            "name": "detail",
            "pattern": "masterList/:detailID:",
            "target": ["master", "detail"]
        }, {
  

Master.view.xml

 <mvc:View controllerName="sap.otuniyi.sample.Master" xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" xmlns="sap.m"
xmlns:semantic="sap.m.semantic">
<semantic:MasterPage id="page" title="Contents">
    <semantic:content>
        <List id="list" items="{/masterList}" mode="SingleSelectMaster" 
            noDataText="No List Found" growing="true" growingScrollToLoad="true" selectionChange="onSelectionChange" updateFinished="onUpdateFinished">
            <items>
                <StandardListItem title="{titleName}" type="Active" press="onSelectionChange" icon="{icon}" description="{description}"/>
            </items>
        </List>
    </semantic:content>
</semantic:MasterPage>
  

Master.controller.js

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

return Controller.extend("sap.otuniyi.sample.Master", {
    onInit : function () {
        this.getOwnerComponent().getRouter().getRoute("master").attachPatternMatched(this._onRouteMatched, this);
    },
    _onRouteMatched: function(oEvent) {
        if(!Device.system.phone) {
            this.getOwnerComponent().getRouter()
                .navTo("detail", {detailID: 0}, true);              
        }
    },
    onSelectionChange: function(oEvent) {
        var sdetailID = oEvent.getSource().getSelectedItem().getBindingContext().getProperty("detailID");
        this.getOwnerComponent().getRouter()
            .navTo("detail", 
                {detailID:sdetailID}, 
                !Device.system.phone);
    }
});},  true);
  

Detail.view.xml

 <mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:layout="sap.ui.layout" controllerName="sap.otuniyi.sample.Detail"
xmlns:semantic="sap.m.semantic">
<semantic:DetailPage id="page" title="{i18n>detailTitle}" navButtonPress="onNavBack">
    <semantic:content>
        <List id="DetailsId" items="{titlesProperties}" headerText="Buttons" updateFinished="onListUpdateFinished"
            noDataText="No detail Data" selectionChange="onSelectionChange" class="sapUiResponsiveMargin">
            <items>
                <StandardListItem title="{subDetailID}" type="Active" press="onSelectionChange"/>
            </items>
        </List>
    </semantic:content>
</semantic:DetailPage>
  

Detail.controller.js

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

return Controller.extend("sap.otuniyi.sample", {
    onInit: function() {
        this.getOwnerComponent().getRouter().getRoute("detail").attachPatternMatched(this._onRouteMatched, this);
    },
    _onRouteMatched: function(oEvent) {
        this._detailID = oEvent.getParameter("arguments").detailID;
        this.getView().bindElement("/masterList/"   this._detailID);
    },

    onSelectionChange: function(oEvent) {
        var bReplace = !Device.system.phone;
        var sID = oEvent.getSource().getBindingContext().getProperty("subDetailID");

        this.getOwnerComponent().getRouter().navTo("subDetail", {
            detailID: this._detailID,
            subDetailID: sID
        }, !bReplace);
    }

});}, true);