SAP Fiori 实战课程(二):新建页面

课程回顾

上一课中,利用Visual studio Code 新建、并运行了一个Demo工程。可以实现对项目的启动,启动后进入一个List清单。

那么本次课程的目前就是在上一节Demo的基础上,从零开始新建一个完整的页面。实现从首页清单,选择行后,鼠标点击,进入下一个页面。

准备工作

在开始之前,把上一节代码中的页面的显示的清单抽取成一个单独的json文件,这样controller层的代码就显得没有那么臃肿。但是标准版的做法其实是需要把清单数据,直接放到JSONModel对象里面。

这里演示下View层的数据如何从指定文件夹取。

1 首先把product.json文件,放在webapp文件夹下

2 在manifast.json文件内model属性配置如下:

"models": {
      "i18n": {
        "type": "sap.ui.model.resource.ResourceModel",
        "settings": {
          "bundleName": "project1.i18n.i18n"
        }
      },
      "products": {
        "type": "sap.ui.model.json.JSONModel",
        "uri": "products.json"
      },

主要是为了引入products.json文件。

然后修改View1的xml和controller如下:

<mvc:View controllerName="project1.controller.View1"
    xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
    xmlns="sap.m">
    <Page id="page" title="{i18n>title}">
        <content>
        <List
		items="{products>/ProductCollection}"
		headerText="Products">
		<ObjectListItem
			title="{products>Name}"
			type="Active"
			press="onListItemPress"
			number="{
				parts:[{path:'products>Price'},{path:'products>CurrencyCode'}],
				type: 'sap.ui.model.type.Currency',
				formatOptions: {showMeasure: false}
			}"
			numberUnit="{products>CurrencyCode}">
			<firstStatus>
				<ObjectStatus
					text="{products>Status}"
					state="{
						path: 'products>Status',
						formatter: 'project1.controller.Formatter.status'
					}" />
			</firstStatus>
			<ObjectAttribute text="{products>WeightMeasure} {products>WeightUnit}" />
			<ObjectAttribute text="{products>Width} x {products>Depth} x {products>Height} {products>DimUnit}" />
		</ObjectListItem>
	</List>
        </content>
    </Page>
</mvc:View>

主要的区别是所有的属性前面都加入了 products>。

View1.controller.js修改后:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    'sap/m/MessageToast',
    './Formatter',
    'sap/ui/model/json/JSONModel'
],
    /**
     * @param {typeof sap.ui.core.mvc.Controller} Controller
     */
    function (Controller, MessageToast, Formatter, JSONModel) {
        "use strict";

        return Controller.extend("project1.controller.View1", {
            onInit: function () {
            },

            onListItemPress: function (oEvent) {
                MessageToast.show("Pressed : " + oEvent.getSource().getTitle());
            }
        });
    });

 新建详情页面

首先要知道一个前提,Fiori使用了经典的MVC分层理论,即外面前面见过的view.xml视图层,controller.js业务逻辑层,和刚才我们配置的model层:products.json。

相当于把原来一个页面的业务进行了解耦分层,从结构层面来说,功能划分比较清晰。

所以新建页面我们也需要分别新建一整套MVC结构,由于这是一个可以直接用于生产的Demo项目,还要在manifest.json文件配置路由信息。

新建View

在view文件夹下新建文件View1Detail.view.xml:

<mvc:View
	xmlns="sap.m"
	xmlns:core="sap.ui.core"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:f="sap.ui.layout.form"
	controllerName="project1.controller.View1Detail"
	height="100%">

		<f:Form editable="true" class="sapUiSmallMargin" title="Product Detail">
                <f:layout>
                    <f:ResponsiveGridLayout labelSpanXL="3" labelSpanL="3" labelSpanM="3" labelSpanS="12"
                        adjustLabelSpan="false" emptySpanXL="4" emptySpanL="4" emptySpanM="4" emptySpanS="0"
                        columnsXL="1" columnsL="1" columnsM="1" singleContainerFullSize="false" />
                </f:layout>

                <f:formContainers>
                    <f:FormContainer>
                        <f:formElements>
                            <f:FormElement  label="ProductId" >
                                <f:fields>
                                   <Input  value="{/ProductId}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Category" >
                                <f:fields>
                                   <Input  value="{/Category}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="MainCategory" >
                                <f:fields>
                                   <Input  value="{/MainCategory}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="TaxTarifCode" >
                                <f:fields>
                                   <Input  value="{/TaxTarifCode}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="SupplierName" >
                                <f:fields>
                                   <Input  value="{/SupplierName}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="WeightMeasure" >
                                <f:fields>
                                   <Input  value="{/WeightMeasure}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="WeightUnit" >
                                <f:fields>
                                   <Input  value="{/WeightUnit}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Description" >
                                <f:fields>
                                   <Input  value="{/Description}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Name" >
                                <f:fields>
                                   <Input  value="{/Name}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="DateOfSale" >
                                <f:fields>
                                   <Input  value="{/DateOfSale}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="ProductPicUrl" >
                                <f:fields>
                                   <Input  value="{/ProductPicUrl}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Status" >
                                <f:fields>
                                   <Input  value="{/Status}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Quantity" >
                                <f:fields>
                                   <Input  value="{/Quantity}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="UoM" >
                                <f:fields>
                                   <Input  value="{/UoM}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="CurrencyCode" >
                                <f:fields>
                                   <Input  value="{/CurrencyCode}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Price" >
                                <f:fields>
                                   <Input  value="{/Price}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Width" >
                                <f:fields>
                                   <Input  value="{/Width}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Depth" >
                                <f:fields>
                                   <Input  value="{/Depth}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="Height" >
                                <f:fields>
                                   <Input  value="{/Height}" />
                                </f:fields>
                            </f:FormElement>
							<f:FormElement  label="DimUnit" >
                                <f:fields>
                                   <Input  value="{/DimUnit}" />
                                </f:fields>
                            </f:FormElement>
                        </f:formElements>
                    </f:FormContainer>
                </f:formContainers>
            </f:Form>
    

</mvc:View>

新建Controller

controller文件夹下新建js文件View1Detail.controller.js:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    'sap/m/MessageToast',
    './Formatter',
    'sap/ui/model/json/JSONModel'
],
    /**
     * @param {typeof sap.ui.core.mvc.Controller} Controller
     */
    function (Controller, MessageToast, Formatter, JSONModel) {
        "use strict";

        return Controller.extend("project1.controller.View1Detail", {
            onInit: function () {
                var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
                this.oRouter = oRouter;
oRouter.getRoute("View1Detail").attachPatternMatched(this._onObjectMatched, this);

            },

            _onObjectMatched: async function (oEvent) {
                // set explored app's demo model on this sample
                let parameter = oEvent.getParameter("arguments")
                var paramJson = decodeURIComponent(parameter["parameters"]);
                const param = JSON.parse(paramJson)
                this.getView().setModel(new JSONModel(param.data));
            },

        });
    });

注意这里需要注意的是 _onObjectMatched这个回调方法,在生产业务必须加上,否则会出现缓存问题,也就是点击清单第一条,进入了第一条数据详情,如果返回上一级页面,再点击第二条数据,进去看到的还是清单第一条的详情,会造成缓存问题。

新建Model

这里的model其实来源于清单页面点击后触发的函数来赋值的,具体代码如下:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    'sap/m/MessageToast',
    './Formatter',
    'sap/ui/model/json/JSONModel'
],
    /**
     * @param {typeof sap.ui.core.mvc.Controller} Controller
     */
    function (Controller, MessageToast, Formatter, JSONModel) {
        "use strict";

        return Controller.extend("project1.controller.View1", {
            onInit: function () {
                var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
                this.oRouter = oRouter;
            },

            onListItemPress: function (oEvent) {
                MessageToast.show("Pressed : " + oEvent.getSource().getTitle());
                let id = oEvent.oSource.oBindingContexts.products.sPath
                let dataIndex = id.substr(id.lastIndexOf("/") + 1);
                const products = this.getView().getModel("products");
                const productCollection = products.getProperty("/ProductCollection");
                const jsonParam = JSON.stringify({ data: productCollection[dataIndex] });
                this.oRouter.navTo("View1Detail", { parameters: encodeURIComponent(jsonParam) })
            }
        });
    });

可以看到,model数据来源于onListItemPress函数,通过获取当前页面的products模型的数据,再根据点击的行索引找到对应的详情数据,一encodeURI的形式,通过http参数的形式传递到下一个页面。 

新建路由

修改manifest.json文件routing属性:

"routing": {
      "config": {
        "routerClass": "sap.m.routing.Router",
        "viewType": "XML",
        "async": true,
        "viewPath": "project1.view",
        "controlAggregation": "pages",
        "controlId": "app",
        "clearControlAggregation": false
      },
      "routes": [
        {
          "name": "RouteView1",
          "pattern": ":?query:",
          "target": [
            "TargetView1"
          ]
        },
        {
          "name": "View1Detail",
          "pattern": "View1Detail:parameters:",
          "target": "View1Detail"
        }
      ],
      "targets": {
        "TargetView1": {
          "viewType": "XML",
          "transition": "slide",
          "clearControlAggregation": false,
          "viewId": "View1",
          "viewName": "View1"
        },
        "View1Detail": {
          "viewType": "XML",
          "transition": "slide",
          "clearControlAggregation": false,
          "viewId": "View1Detail",
          "viewName": "View1Detail"
        }
      }
    },

详情页面预览

通过点击清单页面后,可显示产品详情:

点击选中行:

显示详情页面 

 结论

从零到一,新建了一个业务页面,有助于快速开放Fiori业务代码。

免费附件

products.json内容如下,无需使用vip下载:

{
    "ProductCollection": [
        {
            "ProductId": "HT-1000",
            "Category": "Laptops",
            "MainCategory": "Computer Systems",
            "TaxTarifCode": "1",
            "SupplierName": "Very Best Screens",
            "WeightMeasure": 4.2,
            "WeightUnit": "KG",
            "Description": "Notebook Basic 15 with 2,80 GHz quad core, 15\" LCD, 4 GB DDR3 RAM, 500 GB Hard Disc, Windows 8 Pro",
            "Name": "Notebook Basic 15",
            "DateOfSale": "2017-03-26",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1000.jpg",
            "Status": "Available",
            "Quantity": 10,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 956,
            "Width": 30,
            "Depth": 18,
            "Height": 3,
            "DimUnit": "cm"
        },
        {
            "ProductId": "HT-1001",
            "Category": "Laptops",
            "MainCategory": "Computer Systems",
            "TaxTarifCode": "1",
            "SupplierName": "Very Best Screens",
            "WeightMeasure": 4.5,
            "WeightUnit": "KG",
            "Description": "Notebook Basic 17 with 2,80 GHz quad core, 17\" LCD, 4 GB DDR3 RAM, 500 GB Hard Disc, Windows 8 Pro",
            "Name": "Notebook Basic 17",
            "DateOfSale": "2017-04-17",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1001.jpg",
            "Status": "Available",
            "Quantity": 20,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 1249,
            "Width": 29,
            "Depth": 17,
            "Height": 3.1,
            "DimUnit": "cm"
        },
        {
            "ProductId": "HT-1002",
            "Category": "Laptops",
            "MainCategory": "Computer Systems",
            "TaxTarifCode": "1",
            "SupplierName": "Very Best Screens",
            "WeightMeasure": 4.2,
            "WeightUnit": "KG",
            "Description": "Notebook Basic 18 with 2,80 GHz quad core, 18\" LCD, 8 GB DDR3 RAM, 1000 GB Hard Disc, Windows 8 Pro",
            "Name": "Notebook Basic 18",
            "DateOfSale": "2017-01-07",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1002.jpg",
            "Status": "Available",
            "Quantity": 10,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 1570,
            "Width": 28,
            "Depth": 19,
            "Height": 2.5,
            "DimUnit": "cm"
        },
        {
            "ProductId": "HT-1003",
            "Category": "Laptops",
            "MainCategory": "Computer Systems",
            "TaxTarifCode": "1",
            "SupplierName": "Smartcards",
            "WeightMeasure": 4.2,
            "WeightUnit": "KG",
            "Description": "Notebook Basic 19 with 2,80 GHz quad core, 19\" LCD, 8 GB DDR3 RAM, 1000 GB Hard Disc, Windows 8 Pro",
            "Name": "Notebook Basic 19",
            "DateOfSale": "2017-04-09",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1003.jpg",
            "Status": "Available",
            "Quantity": 15,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 1650,
            "Width": 32,
            "Depth": 21,
            "Height": 4,
            "DimUnit": "cm"
        },
        {
            "ProductId": "HT-1007",
            "Category": "Accessories",
            "MainCategory": "Computer Components",
            "TaxTarifCode": "1",
            "SupplierName": "Technocom",
            "WeightMeasure": 0.2,
            "WeightUnit": "KG",
            "Description": "Digital Organizer with State-of-the-Art Storage Encryption",
            "Name": "ITelO Vault",
            "DateOfSale": "2017-05-17",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1007.jpg",
            "Status": "Available",
            "Quantity": 15,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 299,
            "Width": 32,
            "Depth": 22,
            "Height": 3,
            "DimUnit": "cm"
        },
        {
            "ProductId": "HT-1258",
            "Category": "Smartphones and Tablets",
            "MainCategory": "Smartphones & Tablets",
            "TaxTarifCode": "1",
            "SupplierName": "Ultrasonic United",
            "WeightMeasure": 2.5,
            "WeightUnit": "KG",
            "Description": "8-inch Multitouch HD Screen (2000 x 1500) 32GB Internal Memory, Wireless N Wi-Fi, Bluetooth, GPS Enabled, 1.5 GHz Quad-Core Processor",
            "Name": "Cepat Tablet 8",
            "ProductPicUrl": "https://sdk.openui5.org/test-resources/sap/ui/documentation/sdk/images/HT-1258.jpg",
            "Status": "Available",
            "Quantity": 24,
            "UoM": "PC",
            "CurrencyCode": "EUR",
            "Price": 529,
            "Width": 38,
            "Depth": 21,
            "Height": 3.5,
            "DimUnit": "cm"
        }
    ],
    "ProductCollectionStats": {
        "Counts": {
            "Total": 123,
            "Weight": {
                "Ok": 53,
                "Heavy": 51,
                "Overweight": 19
            }
        },
        "Groups": {
            "Category": {
                "Accessories" : 34,
                "Desktop Computers" : 7,
                "Flat Screens" : 2,
                "Keyboards" : 4,
                "Laptops" : 11,
                "Printers" : 9,
                "Smartphones and Tablets" : 9,
                "Mice" : 7,
                "Computer System Accessories" : 8,
                "Graphics Card" : 4,
                "Scanners" : 4,
                "Speakers" : 3,
                "Software" : 8,
                "Telekommunikation" : 3,
                "Servers" : 3,
                "Flat Screen TVs" : 3
            },
            "SupplierName": {
                "Titanium": 21,
                "Technocom": 22,
                "Red Point Stores": 7,
                "Very Best Screens": 14,
                "Smartcards": 2,
                "Alpha Printers": 5,
                "Printer for All": 8,
                "Oxynum": 8,
                "Fasttech": 15,
                "Ultrasonic United": 15,
                "Speaker Experts": 3,
                "Brainsoft": 3
            }
        },
        "Filters": [
            {
                "type": "Category",
                "values": [
                    {
                        "text": "Accessories",
                        "data": 34
                    },
                    {
                        "text": "Desktop Computers",
                        "data": 7
                    },
                    {
                        "text": "Flat Screens",
                        "data": 2
                    },
                    {
                        "text": "Keyboards",
                        "data": 4
                    },
                    {
                        "text": "Laptops",
                        "data": 11
                    },
                    {
                        "text": "Printers",
                        "data": 9
                    },
                    {
                        "text": "Smartphones and Tablets",
                        "data": 9
                    },
                    {
                        "text": "Mice",
                        "data": 7
                    },
                    {
                        "text": "Computer System Accessories",
                        "data": 8
                    },
                    {
                        "text": "Graphics Card",
                        "data": 4
                    },
                    {
                        "text": "Scanners",
                        "data": 4
                    },
                    {
                        "text": "Speakers",
                        "data": 3
                    },
                    {
                        "text": "Software",
                        "data": 8
                    },
                    {
                        "text": "Telekommunikation",
                        "data": 3
                    },
                    {
                        "text": "Servers",
                        "data": 3
                    },
                    {
                      "text": "Flat Screen TVs",
                      "data": 3
                    }
                ]
            },
            {
                "type": "SupplierName",
                "values": [
                    {
                    "text": "Titanium",
                    "data": 21
                  },
                  {
                    "text": "Technocom",
                    "data": 22
                  },
                  {
                    "text": "Red Point Stores",
                    "data": 7
                  },
                  {
                    "text": "Very Best Screens",
                    "data": 14
                  },
                  {
                    "text": "Smartcards",
                    "data": 2
                  },
                  {
                    "text": "Alpha Printers",
                    "data": 5
                  },
                  {
                    "text": "Printer for All",
                    "data": 8
                  },
                  {
                    "text": "Oxynum",
                    "data": 8
                  },
                  {
                    "text": "Fasttech",
                    "data": 15
                  },
                  {
                    "text": "Ultrasonic United",
                    "data": 15
                  },
                  {
                    "text": "Speaker Experts",
                    "data": 3
                  },
                  {
                    "text": "Brainsoft",
                    "data": 3
                  }
                ]
            }
        ]
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值