SAPUI5 (19) - 多页面程序及简单的页面导航

Master-detail是一种非常常见的数据关系,比如订单和订单行项目,每个订单包括一个或多个行项目。本篇以供应商清单和供应商明细为例,介绍master-detail的实现方法,并在后续介绍Component的时候,还要用到这个例子,对代码进行重构。我们要实现的功能是:先用一个页面显示供应商清单:

当点击某一个供应商所在行的时候,跳转到供应商明细页面:

并且,点击“返回”按钮的时候,回到概览界面。

如何实现页面跳转

在index.html中定义的app (sap.m.App) 是一个全局对象,通过app.to(sPageId)可以跳转到另外一个页面。

语法to(sPageId, sTransitionName*?*, oData*?*, oTransitionParameters*?*): [sap.m.NavContainer]

Navigates to the next page (with drill-down semantic) with the given (or default) animation. This creates a new history item inside the NavContainer and allows going back.
Note that any modifications to the target page (like setting its title, or anything else that could cause a re-rendering) should be done BEFORE calling to(), in order to avoid unwanted side effects, e.g. related to the page animation.
Available transitions currently include "slide" (default), "fade", "flip", and "show". None of these is currently making use of any given transitionParameters.
Calling this navigation method triggers first the (cancelable) "navigate" event on the NavContainer, then the "beforeHide" pseudo event on the source page and "beforeFirstShow" (if applicable) and"beforeShow" on the target page. Later - after the transition has completed - the "afterShow" pseudo event is triggered on the target page and "afterHide" on the page which has been left. The given data object is available in the "beforeFirstShow", "beforeShow" and "afterShow" event object as "data" property.

app.back()则跳回到刚才的page:

语法: back(oBackData*?*, oTransitionParameters*?*): [sap.m.NavContainer]

Navigates back one level. If already on the initial page and there is no place to go back, nothing happens.
Calling this navigation method triggers first the (cancelable) "navigate" event on the NavContainer, then the "beforeHide" pseudo event on the source page and "beforeFirstShow" (if applicable) and"beforeShow" on the target page. Later - after the transition has completed - the "afterShow" pseudo event is triggered on the target page and "afterHide" on the page which has been left. The given backData object is available in the "beforeFirstShow", "beforeShow" and "afterShow" event object as "data" property. The original "data" object from the "to" navigation is also available in these event objects.

使用jsview实现master-detail

我们将通过jsview和xml view两种方式来展示。先介绍jsview的实现。代码的文件结构如下:

json数据

数据存放在json文件中,文件名为data.json。包括两个供应商的信息:

{
    "CountOfSuppliers" : "2",
    "Suppliers" : [
        {
            "ID": "1",
            "Name": "ABC汽车有限公司",
            "Address": {
                "Street": "东风大道10号",
                "City": "武汉",
                "ZipCode": "430056",
                "Country": "中国"
            }
        },
        {
            "ID": "2",
            "Name": "福建飞驰新能源汽车有限公司",
            "Address": {
                "Street": "福建莆田城厢区荔城北大道1999号",
                "City": "莆田",
                "ZipCode": "123456",
                "Country": "中国"
            }
        }
    ]
}

Master视图

master视图中,使用sap.m.Table来显示供应商清单。sap.m.Table包含header toolbar,在toolbar中显示供应商的数量:

Master.view.js:

sap.ui.jsview("webapp.view.Master", {

    getControllerName : function() {
        return "webapp.controller.Master";
    },

    createContent : function(oController) {
        
        // 定义table的columns
        var aColumns = [
            new sap.m.Column({
                header: new sap.m.Text({text: "ID"})
            }),
            new sap.m.Column({
                header: new sap.m.Text({text: "供应商名称"})
            })
        ];
        
        // 定义template作为line items
        var oTemplate = new sap.m.ColumnListItem({
            type: "Navigation",
            press: [oController.onListPress, oController],
            cells: [
                new sap.m.ObjectIdentifier({text: "{ID}"}),
                new sap.m.ObjectIdentifier({text: "{Name}"})
            ]
        });
        
        // table的toolbar
        var oHeaderToolbar = new sap.m.Toolbar({
            content: [
                new sap.m.Title({text: "供应商数量:{/CountOfSuppliers}"})
            ]
        });
        
        // table
        var oTable = new sap.m.Table({
            columns: aColumns,
            headerToolbar: oHeaderToolbar
        });
        oTable.bindItems("/Suppliers", oTemplate);
        
        // master page
        var oMasterPage = new sap.m.Page({
            title: "供应商概览",
            content: [oTable]
        });
        
        return oMasterPage;
    }

});

注意sap.m.ColumnListItem的type必须为Navigation,否则不能实现跳转。sap.m.ColumnListItem的press属性设置为一个数组,这种方法能够保证在Controller中,this表示Controller本身,而不是某个控件。

Master Controller

Master.controller.js:

sap.ui.define(
    ["sap/ui/core/mvc/Controller"], 
        
    function(Controller){
        "use strict";
        
        return Controller.extend("webapp.controller.Master", {
            onListPress: function(oEvent){
                var sPageId = "detailView";
                oApp.to(sPageId);
                
                var oContext = oEvent.getSource().getBindingContext();
                var oDetailPage = oApp.getPage(sPageId);
                oDetailPage.setBindingContext(oContext);
                
            }
        });
    }
);

在Master controller中,处理ColumnListItem的press事件。当点击的时候,跳转到明细页面,并且将明细页面的BindingContext设置为当前的供应商。比如当选择第一个供应商的时候,oContext为/Suppliers/0,这就是之前文章所介绍的element binding。

Detail View

Detail view负责显示供应商信息,包括供应商ID、名称和地址。
Detail.view.js:

sap.ui.jsview("webapp.view.Detail", {

    getControllerName : function() {
        return "webapp.controller.Detail";
    },

    createContent : function(oController) {
        var oObjectHeader = new sap.m.ObjectHeader({
            title: "{Name}",
            number: "ID: {ID}",
            attributes: [
                new sap.m.ObjectAttribute({
                    text: "{Address/Street}, {Address/City}"
                })
            ]
        });
        
        var oDetailPage = new sap.m.Page({
            showNavButton: true,
            navButtonPress: [oController.onNavPress, oController],
            title: "供应商明细",
            content: [oObjectHeader]
        });
        
        return oDetailPage;
    }

});

sap.m.Page中,showNavButton设置为true,就会出现Navigation按钮,点击按钮的event hander通过Controller中onNavPress函数来实现。

Detail Controller

在Detail controller中,增加onNavPress函数,通过app.back()使得能够退回到供应商概览界面。

Detail.controller.js:

sap.ui.define([
         "sap/ui/core/mvc/Controller"
    ], 
    
    function(Controller){
        return Controller.extend("webapp.controller.Detail",{
            onNavPress: function(oEvent){
                oApp.back();
            }
        });
    }
);

最后就是启动的index.html页面,完整代码如下:

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>

        <script src="resources/sap-ui-core.js"
                id="sap-ui-bootstrap"
                data-sap-ui-libs="sap.m"
                data-sap-ui-xx-bindingSyntax="complex"
                data-sap-ui-resourceroots='{"webapp": "./webapp/"}'
                data-sap-ui-theme="sap_bluecrystal">
        </script>       

        <script>
            // application data
            var oModel = new sap.ui.model.json.JSONModel();
            oModel.loadData("webapp/model/data.json");
            sap.ui.getCore().setModel(oModel);
            
            var oApp = new sap.m.App({
                initialPage: "masterView"
            });
            
            var oMasterView = sap.ui.jsview("masterView", "webapp.view.Master");
            var oDetailView = sap.ui.jsview("detailView", "webapp.view.Detail");
            
            oApp.addPage(oMasterView);
            oApp.addPage(oDetailView);
            oApp.placeAt("content");
            
        </script>

    </head>
    <body class="sapUiBody" role="application">
        <div id="content"></div>
    </body>
</html>

index.html的要点:

  • 因为data.json同时被master view和detail view使用,所以我们将Model中的数据交给core对象,这样整个程序都能看到。

  • 在index.html中,需要加载master view和detail view,并且设置两个view的id,这个id是页面跳转的时候需要使用的id。

xml view实现master-detail

因为之前介绍过xml view,所以在这里,主要贴出代码,不再重复介绍。master controller和detail controller的代码都一样,index.html的主要区别是sap.ui.jsview变为sap.ui.xmlview。文件的代码结构:

index.html

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>

        <script src="resources/sap-ui-core.js"
                id="sap-ui-bootstrap"
                data-sap-ui-libs="sap.m"
                data-sap-ui-xx-bindingSyntax="complex"
                data-sap-ui-resourceroots='{"webapp": "./webapp/"}'
                data-sap-ui-theme="sap_bluecrystal">
        </script>       

        <script>
            // application data
            var oModel = new sap.ui.model.json.JSONModel();
            oModel.loadData("webapp/model/data.json");
            sap.ui.getCore().setModel(oModel);
            
            var oApp = new sap.m.App({
                initialPage: "masterView"
            });
            
            var oMasterView = sap.ui.xmlview({
                id: "masterView",
                viewName: "webapp.view.Master"
            }); 
            
            var oDetailView = sap.ui.xmlview({
                id: "detailView",
                viewName: "webapp.view.Detail"
            });
            
            oApp.addPage(oMasterView);
            oApp.addPage(oDetailView);
            oApp.placeAt("content");
            
        </script>

    </head>
    <body class="sapUiBody" role="application">
        <div id="content" class="sapUiResponsiveMargin"></div>
    </body>
</html>

Master.view.xml:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" 
           xmlns="sap.m"
        controllerName="webapp.controller.Master" 
        xmlns:html="http://www.w3.org/1999/xhtml">
        
    <Page title="供应商概览">
        <content>
            <Table items="{/Suppliers}" >
                <headerToolbar>
                    <Toolbar>
                        <Title text="供应商数量:{/CountOfSuppliers}" />
                    </Toolbar>
                </headerToolbar>
                <columns>
                    <Column>
                        <header><Text text="ID" /></header>
                    </Column>
                    <Column>
                        <header><Text text="供应商名称" /></header>
                    </Column>
                </columns>
                <items>
                    <ColumnListItem type="Navigation" press="onListPress">
                        <cells>
                            <ObjectIdentifier text="{ID}" />
                            <ObjectIdentifier text="{Name}" />
                        </cells>
                    </ColumnListItem>
                </items>
                
            </Table>
        </content>
    </Page> 
</core:View>

Detail.view.xml:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" 
           xmlns="sap.m"
        controllerName="webapp.controller.Detail" 
        xmlns:html="http://www.w3.org/1999/xhtml">
        
    <Page title="供应商明细" showNavButton="true" navButtonPress="onNavPress">
        <content>
            <ObjectHeader title="{Name}" 
                number="ID: {ID}">
                <attributes>
                    <ObjectAttribute text="{Address/Street}, {Address/City}" />
                </attributes>
            
            </ObjectHeader>
        </content>
    </Page>
    
</core:View>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • 戒烟何时都不晚,戒烟也并非想象中的那么难。因为你可以在戒烟的时候,吃特定的食物来帮助你戒烟。 例如,吃这10种食物...
    大东教练阅读 3,387评论 0 2
  • 双cpu模式: L模式,线性,一个负责逻辑思维和语言处理 R模式,非线性,一个多维度、跳跃、非语言性是思维 eg:...
    零丁阅读 269评论 4 1
  • 正式开始博客生涯 为了明年秋季的校园招聘和暑期实习,终于要结束为期一年半的不学无术生涯了,硕士期间做了计算机视觉的...
    YoghurtIce阅读 388评论 1 0
  • 首先感谢千里之外的丹丹赞助的小米手环2 与一代相比,小米手环2(以下简称米环2)的主要有2个大改变 增加屏幕,可以...
    罗非阅读 1,229评论 0 3