이번 튜토리얼에서는 직원 목록중 직원 클릭시 세부 정보를 볼 수 있는 기능을 구현한다. 라우트 패턴은 App의 개체를 식별하기 위해 1개 이상의 parameter 변수를 가진다.

Preview

07_preview1.png

직원 정보 페이지

07_preview2.png

없는 직원 정보 페이지

Coding

Routing and Navigation - Step 7.

webapp/manifest.json

{
    ...,
    "sap.ui5": {
        ...,
        "routing": {
            "config": {
                "routerClass": "sap.m.routing.Router",
                "viewType": "XML",
                "viewPath": "sap.ui.demo.nav.view",
                "controlId": "app",
                "controlAggregation": "pages",
                "transition": "slide",
                "bypassed": {
                    "target": "notFound"
                }
            },
            "routes": [{
                "pattern": "",
                "name": "appHome",
                "target": "home"
            }, {
                "pattern": "employees",
                "name": "employeeList",
                "target": "employees"
            }, {
                "pattern": "employees/{employeeId}",
                "name": "employee",
                "target": "employee"
            }],
            "targets": {
                "home": {
                    "viewId": "home",
                    "viewName": "Home",
                    "viewLevel" : 1
                },
                "notFound": {
                    "viewId": "notFound",
                    "viewName": "NotFound",
                    "transition": "show"
                },
                "employees": {
                    "viewId": "employeeList",
                    "viewPath": "sap.ui.demo.nav.view.employee",
                    "viewName": "EmployeeList",
                    "viewLevel" : 2
                },
                "employee": {
                    "viewId": "employee",
                    "viewName": "employee.Employee",
                    "viewLevel" : 3
                }
            }
        }
    }
}

데이터 모델 (Employees.json 파일)을 보면 직원 엔티티는 EmployeddID로 식별된다. descriptor 파일에 새로운 라우트 정의한다.
새로운 라우트 pattern 속성의 employees/{employeeId} 부분은 매개 변수로 실제 employee ID가 들어있는 hash는 해당 pattern과 일차하게 된다.
ex) http://localhost:8080/index.html#/employees/1 -> (EmployeddID)

webapp/view/employee/Employee.view.xml (New)

<mvc:View
    controllerName="sap.ui.demo.nav.controller.employee.Employee"
    xmlns="sap.m"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns:f="sap.ui.layout.form"
    busyIndicatorDelay="0">
    <Page
        id="employeePage"
        title="{i18n>EmployeeDetailsOf} {FirstName} {LastName}"
        showNavButton="true"
        navButtonPress="onNavBack"
        class="sapUiResponsiveContentPadding">
        <content>
            <Panel
                id="employeePanel"
                width="auto"
                class="sapUiResponsiveMargin sapUiNoContentPadding">
                <headerToolbar>
                    <Toolbar>
                        <Title text="{i18n>EmployeeIDColon} {EmployeeID}" level="H2"/>
                        <ToolbarSpacer />
                    </Toolbar>
                </headerToolbar>
                <content>
                    <f:SimpleForm
                        minWidth="1024"
                        editable="false"
                        layout="ResponsiveGridLayout"
                        labelSpanL="3" labelSpanM="3" emptySpanL="4" emptySpanM="4"
                        columnsL="1" columnsM="1">
                        <f:content>
                            <Label text="{i18n>FirstName}" />
                            <Text text="{FirstName}" />
                            <Label text="{i18n>LastName}" />
                            <Text text="{LastName}" />
                            <Label text="{i18n>Address}" />
                            <Text text="{Address}" />
                            <Label text="{i18n>City}" />
                            <Text text="{City}, {Region}" />
                            <Label text="{i18n>PostalCode}" />
                            <Text text="{PostalCode}" />
                            <Label text="{i18n>PhoneHome}" />
                            <Text text="{HomePhone}" />
                            <Label text="{i18n>Country}" />
                            <Text text="{Country}" />
                        </f:content>
                    </f:SimpleForm>
                </content>
            </Panel>
        </content>
    </Page>
</mvc:View>

webapp/view/employee 경로에 Employee.view.xml파일을 생성한다.
sap.ui.layout.form 컨트롤 안에 있는 Panel 컨트롤을 통해 employee 데이터를 표시한다.

webapp/controller/employee/Employee.controller.js (New)

sap.ui.define([
    "sap/ui/demo/nav/controller/BaseController"
], function (BaseController) {
    "use strict";

    return BaseController.extend("sap.ui.demo.nav.controller.employee.Employee", {

        onInit: function () {
            var oRouter = this.getRouter();

            oRouter.getRoute("employee").attachMatched(this._onRouteMatched, this);

            // Hint: we don't want to do it this way
            /*
            oRouter.attachRouteMatched(function (oEvent){
                var sRouteName, oArgs, oView;

                sRouteName = oEvent.getParameter("name");
                if (sRouteName === "employee"){
                    this._onRouteMatched(oEvent);
                }
            }, this);
            */

        },

        _onRouteMatched : function (oEvent) {
            var oArgs, oView;

            oArgs = oEvent.getParameter("arguments");
            oView = this.getView();

            oView.bindElement({
                path : "/Employees(" + oArgs.employeeId + ")",
                events : {
                    change: this._onBindingChange.bind(this),
                    dataRequested: function (oEvent) {
                        oView.setBusy(true);
                    },
                    dataReceived: function (oEvent) {
                        oView.setBusy(false);
                    }
                }
            });
        },

        _onBindingChange : function (oEvent) {
            // No data for the binding
            if (!this.getView().getBindingContext()) {
                this.getRouter().getTargets().display("notFound");
            }
        }

    });

});

webapp/controller/employee 경로에서 Employee.controller.js 파일을 생성한다. 이 컨트롤러에서 _onRouteMatched 함수를 init에서 불러와 직원의 데이터를 view에 표시를 한다.
_onRouteMatched 함수에 매개변수 oEvent을 통해 우리의 모든 parttern을 포함하는 arguments를 액세스 할 수 있다. 해당 리스터는 라우트가 일치할 때만 호출이 되기 때문에
매개 변수 employeeId를 키로 사용한다 해당 employeeId 값은 라우트의 pattern {employeddId}이다.
데이터가 로드되는 동안 oView.bindElement()에 이벤트 객체를 전달하여 dataRequested 및 dataReceived 이벤트를 수신한다. true, false의 값으로 각 호출 상태를 처리한다.

_onBindingChange 함수에서 view의 바인딩 context가 있는지 확인하어 없으면 notFound 페이지로 가게 처리한다.

note:
Route에서 attachMatched() 대신 attachRouteMatched()를 호출할 수 있다 하지만 이는 App 전체의 route가 일치하는지 이벤트를 발생시킨다.
현재 우리가 할 튜토리얼은 현재 경로가 있는 경로인지 체크하기 위한 로직이기에 attachMatched() 사용하여 불필요한 오버헤드를 방지한다.

webapp/view/employee/EmployeeList.view.xml

<mvc:View
    controllerName="sap.ui.demo.nav.controller.employee.EmployeeList"
    xmlns="sap.m"
    xmlns:mvc="sap.ui.core.mvc">
    <Page id="employeeListPage" title="{i18n>EmployeeList}"
        showNavButton="true"
        navButtonPress="onNavBack"
        class="sapUiResponsiveContentPadding">
        <content>
            <List id="employeeList" headerText="{i18n>ListOfAllEmployees}" items="{/Employees}">
                <items>
                    <StandardListItem
                        title="{FirstName} {LastName}"
                        iconDensityAware="false"
                        iconInset="false"
                        type="Navigation"
                        press="onListItemPressed"/>
                </items>
            </List>
        </content>
    </Page>
</mvc:View>

EmployeeList.view에서 StandardListItem 컨트롤에 type을 Navigation으로 설정하여 직원 목록을 클릭 할 수 있게 구현한다.
또한 item을 클릭할 때 호출되는 press 이벤트를 추가한다.

webapp/controller/employee/EmployeeList.controller.js

sap.ui.define([
    "sap/ui/demo/nav/controller/BaseController"
], function (BaseController) {
    "use strict";
    return BaseController.extend("sap.ui.demo.nav.controller.employee.EmployeeList", {
     onListItemPressed : function(oEvent){
            var oItem, oCtx;
            oItem = oEvent.getSource();
            oCtx = oItem.getBindingContext();
            this.getRouter().navTo("employee",{
                employeeId : oCtx.getProperty("EmployeeID")
            });
        }
    });
});

EmployeeList view에 등록한 onListItemPressed 이벤트 핸들러를 컨트롤러에 추가한다. getBindingContext()을 통해 EmployeeID를 모델로 부터 불러온다.
이를 naTo() 메소드로 전달하고 라우터는 pattern에 저장된 필수 매개 변수가 설정되어 있는지 확인하고 아니면 오류가 발생한다.

webapp/i18n/i18n.properties

...
EmployeeDetailsOf=Employee Details of
EmployeeIDColon=Employee ID:
FirstName=First Name
LastName=Last Name
Address=Address
City=City
PostalCode=Postal Code
PhoneHome=Phone (Home)
Country=Country