0
votes

I have some issues with passing parameters from master to detail page in a SplitApp. I use a local JSON file which is specified as a model in the manifest.json.

I can pass the Id of an Object, but in that case, I can't figure out, how to receive the corresponding element in the detail view, to bind it to the view.

I also tried to pass the path of the element, but in this case, the url doesn't change after I select a list item.

Any ideas, how I can display the details on the detail page?

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

2 Answers

0
votes

I would recommend to use the ID instead of the binding path because the route URL is bookmarkable. When using the binding path, the selected detail may change when the collection changes.

A JSONModel has no concept of metadata or keys. So you have to search the model for an item and construct the binding path on your own:

           _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;
                   }
                }
            }   
0
votes

Try setting the model globally in Component.js, binding context could be missing or route isnt matched, have a look at this application, showing how to navigate between master and double detail views Master-Detail Example

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