이번 튜토리얼에서는 재사용 개념을 확장하고 component level에서 다이얼로그를 호출해본다.

Step 16에서 fragment을 통해 다이얼로그를 만들었고 view또는 전체 App에서 재사용 할 수 있도록 했다.
그러나 우리는 다이얼로그 instance 관련 로직을 HelloPanel View의 Controller로 배치했다.
이러면 다이얼로그가 필요할때 마다 각각 view의 Controller에 코드를 계속해서 붙여 넣어야한다.
Step19에선 재사용 개념을 확장하고 component level에서 대화 상자를 호출한다.

Preview

19_preview.png

Coding

Walkthrough - Step 19.

webapp/Component.js

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/model/json/JSONModel",
    "./controller/HelloDialog"

], function (UIComponent, JSONModel, HelloDialog) {
    "use strict";
    return UIComponent.extend("sap.ui.demo.walkthrough.Component", {
        metadata : {
            manifest : "json"
        },
        init : function () {
            // call the init function of the parent
            UIComponent.prototype.init.apply(this, arguments);
            // set data model
            var oData = {
                recipient : {
                    name : "World"
                }
            };
            var oModel = new JSONModel(oData);
            this.setModel(oModel);

            // set dialog
            this._helloDialog = new HelloDialog(this.getRootControl());
        },


        exit : function() {
            this._helloDialog.destroy();
            delete this._helloDialog;
        },

        openHelloDialog : function () {
            this._helloDialog.open();
        }
    });
});

다이얼로그를 인스턴스화는 component의 Helper Object로 리팩토된다.
헬퍼 객체를 인스턴스화하려면, 다이얼로그가 추가된 View를 전달해야한다.
(헬퍼 객체는 HelloDialog.js의 addDependent Method호출을 통해 view에 참조된다)
컨트롤러에 있는 HelloDialog를 앱 루트컨트롤의 라이프 사이클에 연결하여 생성자에 전달한다.
컴포넌트의 getRootControl 메소드를 호출하여 이를 검색 할 수 있다.

note: manifest.json 파일의 rootView 매개 변수에 정의된 루트뷰는 sap.ui.demo.walkthrough.view.App이다.
component에서 rootControl aggregation에 접근하여 런타임에 Root View를 참조 할 수 있다.

다른 컨트롤러(Root View에 속한 Nested view를 관장하는 다른 Controller)에서도 다이얼로그를 사용할 수 있도록
헬퍼 객체의 open 메소드를 호출하는 함수 openHelloDialog를 구현한다.
다이얼로그는 이제 독립적으로 어디서든 사용이 가능 하다.
응용 프로그램에서 메모리 누수를 체크하기 위해 Helper Object에 할당 된 메모리가 구성 요소가 소멸될 때 해제되는지 확인해보자
exit 함수에 this._helloDialog.destroy()를 통해 component를 삭제할 때 종료되도록 지정된 함수를 호출한다.
그럼에도 불구하고 인스턴스 자체는 여전히 브라우저 메모리에 존재한다.
따라서 delete this._helloDialog를 호출하여 HelloDialog 인스턴스에 대한 참조를 삭제하고
브라우저의 가비지 콜렉터가 메모리를 정리할 수 있도록 해준다.

webapp/controller/HelloDialog.js (New)

sap.ui.define([
    "sap/ui/base/ManagedObject",
    "sap/ui/core/Fragment"
], function (ManagedObject, Fragment) {
    "use strict";

    return ManagedObject.extend("sap.ui.demo.walkthrough.controller.HelloDialog", {

        constructor : function (oView) {
            this._oView = oView;
        },

        exit : function () {
            delete this._oView;
        },

        open : function () {
            var oView = this._oView;

            // create dialog lazily
            if (!oView.byId("helloDialog")) {
                var oFragmentController = {
                    onCloseDialog : function () {
                        oView.byId("helloDialog").close();
                    }
                };
                // load asynchronous XML fragment
                Fragment.load({
                    id: oView.getId(),
                    name: "sap.ui.demo.walkthrough.view.HelloDialog",
                    controller: oFragmentController
                }).then(function (oDialog) {
                    // connect dialog to the root view of this component (models, lifecycle)
                    oView.addDependent(oDialog);
                    oDialog.open();
                });
            } else {
                oView.byId("helloDialog").open();
            }
        }

    });

});

HelloDialog 재사용 객체의 구현은 sap.ui.base.ManagedObject 객체를 상속받는다.
open 메소드는 HelloPanel의 Controller로 리팩토링되고 다이얼로그 fragment를 인스턴스화한다.

note: Fragment.load의 controller를 fragment을 위해 필요한 이벤트 핸들러 함수 onCloseDialog를 포함하는
local helper object 인 oFragmentContoller를 전달한다.

open method에는 다이얼로그를 instance하는 내용이 포함되어있다.
open 메소드가 처음 호출되면 다이얼로그가 instance된다.
이 메소드의 oView 인수는 현재진행중인 view를 Dialog에 연결하는 데 사용된다.
onCloseDialog 이벤트 핸들러는 HelloPanel의 Controller로 부터 reuse object로 옮겨졌다.
객체가 destroy 될 때 자동으로 호출되는 exit 함수를 추가한다.
헬퍼 객체의 할당 된 메모리를 모두 비우기 위해 view 에 대한 참조를 보유하는 속성을 삭제한다.
view 자체는 component에 의해 destroy되므로 고려하지 않아도된다.

webapp/controller/HelloPanel.controller.js

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/m/MessageToast"
], function (Controller, MessageToast) {
    "use strict";
    return Controller.extend("sap.ui.demo.walkthrough.controller.HelloPanel", {
        onShowHello : function () {
            // read msg from i18n model
            var oBundle = this.getView().getModel("i18n").getResourceBundle();
            var sRecipient = this.getView().getModel().getProperty("/recipient/name");
            var sMsg = oBundle.getText("helloMsg", [sRecipient]);
            // show message
            MessageToast.show(sMsg);
        },
        onOpenDialog : function () {
            this.getOwnerComponent().openHelloDialog();
        }
    });
});

이제 onOpenDialog method는 익명 함수로 구동된다.
현재 this로 부터 상위 Component정보를 얻는다.
this.getOwnerComponent()에서 Component에 선언 되어있는 openHelloDialog를 호출한다.

webapp/view/App.view.xml

<mvc:View
    controllerName="sap.ui.demo.walkthrough.controller.App"
    xmlns="sap.m"
    xmlns:mvc="sap.ui.core.mvc"
    displayBlock="true">
    <Shell>
        <App class="myAppDemoWT">
            <pages>
                <Page title="{i18n>homePageTitle}">
                    <headerContent>
                        <Button
                            icon="sap-icon://hello-world"
                            press=".onOpenDialog"/>
                    </headerContent>

                    <content>
                        <mvc:XMLView viewName="sap.ui.demo.walkthrough.view.HelloPanel"/>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

Hello World다이얼로그가 재사용 될 수 있는지 확인하기 위해 App View 의 Header Area에 버튼을 추가한다.
버튼을 누르면 다이얼로그가 열릴 것이다.

webapp/controller/App.controller.js

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

    return Controller.extend("sap.ui.demo.walkthrough.controller.App", {

        onOpenDialog : function () {
            this.getOwnerComponent().openHelloDialog();
        }
    });

});

onOpenDialog 메서드를 앱 컨트롤러에 추가하여 다이얼로그가 열리도록 한다.

Conventions

  • 여러 컨트롤러에서 사용되는 재사용할 코드들은 별도의 모듈로 만든다.

Memory Management on https://developer.mozilla.orgInformation published on non-SAP site

API Reference: sap.ui.base.ManagedObject