이번 튜토리얼은 view를 조합할 수 있는 fragment라는 다른 element를 알아본다.

fragment은 재사용 할 수 있고 controller가 없는 가벼운 UI(UI subtrees)이다.
fragment는 1~n 개의 컨트롤로 구성 될 수 있다.
fragment 내부의 컨트롤은 렌더링 될 때 view의 DOM에 포함된다.
App에 다이얼로그를 추가 할 때 App 콘텐츠 상단에서 열리기 때문에 특정 view에 속하지 않는다.
이는 다이얼로그가 controller 코드의 어딘가에서 인스턴스화되어야 함을 의미하지만
유연하고 재사용가능한 구조물(artifacts)을 생성하기위해 XML fragment를 만들어 다이얼로그를 포함시킨다.
따라서 다이얼로그는 앞으로 App내부에서 어디서든 사용할 수 있다.

Preview

16_preview.png

Coding

Walkthrough - Step 16.

webapp/view/HelloPanel.view.xml

<mvc:View
   controllerName="sap.ui.demo.walkthrough.controller.HelloPanel"
   xmlns="sap.m"
   xmlns:mvc="sap.ui.core.mvc">
   <Panel
      headerText="{i18n>helloPanelTitle}"
      class="sapUiResponsiveMargin"
      width="auto" >
      <content>
      <Button
         id="helloDialogButton"
         text="{i18n>openDialogButtonText}"
         press=".onOpenDialog"
         class="sapUiSmallMarginEnd"/>

      <Button
         text="{i18n>showHelloButtonText}"
         press=".onShowHello"
         class="myCustomButton"/>
      <Input
         value="{/recipient/name}"
         valueLiveUpdate="true"
         width="60%"/>
      <FormattedText
         htmlText="Hello {/recipient/name}"
         class="sapUiSmallMargin sapThemeHighlight-asColor myCustomText"/>
      </content>
   </Panel>
</mvc:View>

새로운 <Button>을 추가하여 다이얼로그를 연다.
<Panel><content> 뷰의 컨트롤러에서 이벤트 핸들러 함수를 콜백한다.
id = "helloDialogButton"이 필요하다. 만약 id가 지정되지 않으면 OpenUI5 런타임은 컨트롤에 대해 '__button23'과 같이 고유하지만 변경된 ID를 생성한다.

webapp/view/HelloDialog.fragment.xml (New)

<core:FragmentDefinition
   xmlns="sap.m"
   xmlns:core="sap.ui.core" >
   <Dialog
      id="helloDialog"
      title="Hello {/recipient/name}">
   </Dialog>
</core:FragmentDefinition>

새로운 XML 파일을 추가하여 다이얼로그를 fragment내부에 정의한다.
fragment 애셋은 core 네임스페이스에 있으므로 FragmentDefinition 태그 내에 XML 네임 스페이스를 추가한다.

fragments에는 controller 속성이 없다. 또한 fragments 는 App의 DOM Tree에 footprint가 없으며 fragments control자체 instance가 없다(fragment내에 있는 컨트롤 만 허용)
이것은 재사용 control을 담는 container일 뿐이다.
Dialog가 HelloPanel controller에서 대화 상자에 액세스 할 수 있도록 ID를 추가한다.

webapp/controller/HelloPanel.controller.js

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

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

        onShowHello : function () {},
        onOpenDialog : function () {
            var oView = this.getView();

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

    });
});

프래그먼트의 다이얼로그가 아직 존재하지 않으면 sap.ui.xmlfragment 메소드를 호출하여 프래그먼트가 인스턴스화 된다.
HelloPanel 뷰의 ID가 있다면 해당 아이디를 불러온다.
Fragment 매개변수는 내부에서 접두어 형태로 사용된다.
여기서 다이얼로그 컨트롤에 대한 helloDialog의 ID를 정의하고 oView.byId( "helloDialog")를 호출하여
view를 통해 다이얼로그에 액세스 할 수 있다.

이렇게하면 동일한 view에서 동일한 fragment을 동일한 방식으로 인스턴스화하더라도
각 대화 상자에는 뷰 ID와 다이얼로그 ID에서 연결된 고유 ID가 있어 구분된다.
중복 ID는 프레임 워크에서 오류를 유발하므로 고유 ID를 사용해야 한다.

Conventions

  • UI 트리에 추가되지는 않았지만 항상 addDependent 메서드를 사용하여 다이어로그를 뷰의 라이프 사이클 관리 및 데이터 바인딩에 연결한다.

  • 내부 함수와 변수는 항상 밑줄로 시작한다.

Reusing UI Parts: Fragments

Dialogs and other Popups as Fragments

Stable IDs: All You Need to Know

API Reference: sap.ui.core.Fragment