factory 함수를 사용하여 훨씬 더 유연하고 복잡한 데이터를 표시 할 수 있다.

Preview

15_preview.png

Coding

Data Binding - Step 15.

webapp/view/App.view.xml

... 
    <Panel headerText="{i18n>panel3HeaderText}" class="sapUiResponsiveMargin" width="auto">
        <content>
            <List
                id="ProductList"
                headerText="{i18n>productListTitle}"
                items="{
                    path: 'products>/Products',
                    factory: '.productListFactory'
                }">
                <dependents>
                    <core:Fragment fragmentName="sap.ui.demo.db.view.ProductSimple" type="XML"/>
                    <core:Fragment fragmentName="sap.ui.demo.db.view.ProductExtended" type="XML"/>
                </dependents>
            </List>

        </content>
    </Panel>
...

List 컨트롤에 factory 속성을 추가한다. 만약 데이터가 없다면 List 컨트롤은 비어있게 된다.

webapp/controller/App.controller.js

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/m/library",
    "sap/ui/core/Locale",
    "sap/ui/core/LocaleData",
    "sap/ui/model/type/Currency",
    "sap/m/ObjectAttribute"
], function (Controller, mobileLibrary, Locale, LocaleData, Currency, ObjectAttribute) {
    "use strict";

    return Controller.extend("sap.ui.demo.db.controller.App", {
        ...
        productListFactory : function(sId, oContext) {
            var oUIControl;

            // Decide based on the data which dependant to clone
            if (oContext.getProperty("UnitsInStock") === 0 && oContext.getProperty("Discontinued")) {
                // The item is discontinued, so use a StandardListItem
                oUIControl = this.byId("productSimple").clone(sId);
            } else {
                // The item is available, so we will create an ObjectListItem
                oUIControl = this.byId("productExtended").clone(sId);

                // The item is temporarily out of stock, so we will add a status
                if (oContext.getProperty("UnitsInStock") < 1) {
                    oUIControl.addAttribute(new ObjectAttribute({
                        text : {
                            path: "i18n>outOfStock"
                        }
                    }));
                }
            }

            return oUIControl;
        }

    });
});

App 컨트롤러에서 productListFactory라는 새 함수를 만든다.
factory function은 associated binding context에 대한 control를 리턴한다.
이 factory 함수가 반환하는 컨트롤 유형은 sap.m.List 객체의 item aggregation 이다.
생성 될 항목의 컨텍스트에 저장된 데이터를 기반으로 StandardListItem 또는 ObjectListItem 중 하나를 반환한다.

현재 재고 수준을 확인하여 제품이 중단되었는지 여부를 확인할 유형을 결정하자.
두 옵션 모두 XML fragment을 준비하고 로드하므로 view 로직을 선언적으로 정의하고 현재 컨트롤러를 지정할 수 있다.
재고 수준이 0이고 제품이 중단 된 경우 ProductSimple XML fragment을 사용하고 그렇지 않으면 ProductExtended XML fragment을 사용한다.

XML fragment은 한 번만 로드하면 되므로 controller에 helper variable를 저장하고 한번만 로드하여 Singleton을 만든다.
목록의 각 항목에 대해 controller에 저장된 해당 control을 복제한다.
이렇게하면 List item의 context에 바인딩 할 수있는 새로운 control 사본이 만들어진다.

제품이 중단되지 않았지만 재고가 0이면 JavaScript를 사용하여 i18n>outOfStock 메시지를 control에 추가하는 Attribute ObjectAttribute를 추가한다.
Attribute는 List Item의 하위 항목이므로 할당 된 모든 model과 현재 바인딩 context에 액세스 할 수 있다.

webapp/view/ProductSimple.fragment.xml (new)

<core:FragmentDefinition
    xmlns="sap.m"
    xmlns:core="sap.ui.core">
    <StandardListItem
        icon="sap-icon://warning"
        title="{products>ProductName} ({products>QuantityPerUnit})"
        info="{i18n>Discontinued}"
        type="Active"
        infoState="Error"
        press="onItemSelected">
    </StandardListItem>
</core:FragmentDefinition>

XML fragment은 재고 레벨이 0이고 제품이 단종 된 경우에 사용되는 StandardListItem을 정의한다.

webapp/view/ProductExtended.fragment.xml (new)

<core:FragmentDefinition
    xmlns="sap.m"
    xmlns:core="sap.ui.core">
    <ObjectListItem
        title="{products>ProductName} ({products>QuantityPerUnit})"
        number="{
            parts: [
                {path: 'products>UnitPrice'},
                {path: '/currencyCode'}
            ],
            type: 'sap.ui.model.type.Currency',
            formatOptions : {
                showMeasure : false
            }
        }"
        type="Active"
        numberUnit="{/currencyCode}"
        press="onItemSelected">
    </ObjectListItem>
</core:FragmentDefinition>

확장된 사용사례에서 ObjectListItem을 생성하여 제품의 더 자세한 정보를 표시한다.
Property은 현재 데이터 바인딩 context의 필드에 바인딩되므로 controller에 할당되어 있는 모든 type/formatter/handler의 모든 자원을 사용할 수 있다.

xml에서는 복잡한 논리를 선언적으로 정의 할 수 없다 따라서 재고 수준이 0 일 때 JavaScript를 사용하여 컨트롤러에 재고 없음 메세지를 표시하는 단일 ObjectAttribute를 추가한다.

webapp/i18n/i18n.properties

...
# Product Details
...
outOfStock=Out of Stock

webapp/i18n/i18n_de.properties

...
# Product Details
...
outOfStock=Nicht vorr\u00e4tig

List Binding (Aggregation Binding)

XML Fragments

Using Factory Functions