guide Tutorial

간단한 예제에서 시작해서 RealGrid-Touch 라이브러리를 사용하는 방법을 연습해 본다.

HTML

라이브러리를 사용하기 위해서는 css, 라이선스, 모듈 세 파일이 html에 inlcude 돼야 한다.

<link href="../styles/realgrid-touch-style.css" rel="stylesheet">
<script type="text/javascript" src="../lib/realgrid-touch-lic.js"></script>
<script type="text/javascript" src="../lib/realgrid-touch-1.x.x.min.js"></script>

이어지는 예제들은 별도의 js 파일에 코드가 들어있고 html 파일에서 문서 시작 시점에 init 함수가 호출된다고 가정한다.

<script>
window.addEventListener('DOMContentLoaded', function () {
    init();
});
</script>

Hello World

새로운 언어 공부를 시작할 때 처럼 'Hello, World'를 리스트 컨트롤에 표시해 본다.

function init() {
    RealTouch.createListControl(document, "realtouch").data = RealTouch.createListData("", null, [{
        message: 'Hello, World!'
    }]);
}

(컨트롤 상단의 푸른색 bar는 ScrollIndicator이다.)
image-01
두개의 주요 함수가 RealTouch 모듈 namespace로 호출됐다. createListControl는 리스트 컨트롤을 생성하고, 컨트롤의 data 속성에 createListData로 생성한 데이터소스를 컨트롤에 연결한다.
데이터소스 생성 시 json 배열로 전달한 값들을 이용해 초기 데이터행들을 생성할 수 있다.
리스트 컨트롤의 기본 스타일은 "realgrid-touch-style.css" 파일에 포함된 css 설정으로 구현된다. html 파일에서 기본 폰트 크기를 변경해 본다.

<style>
.rtc-root {
    font-size: 30px;
    color: red;
}
</style>

'.rtc-root'는 최상위 selctor이다.
image-02

리스트 컨트롤은 당연히 여러 행을 표시할 수 있다.

RealTouch.createListControl(document, "realtouch").data = RealTouch.createListData("", null, [{
    message: 'Hello, World!'
}, {
    message: 'Goodbye, Earth!'
}]);

image-03

Configuration & Options

컨트롤은 데이터행을 표시하는 것 외에 여러 기능과 표시 영역들이 존재한다. 이런 기능과 영역들은 또한 여러 상태를 가질 수 있는데, 컨트롤 생성 후, setConfig 함수 호출로 초기 상태들을 설정할 수 있다. 설정 객체는 크게 "props", "options", "portrait", "landscape" 하위 설정 객체들로 나뉘어 진다. props에는 모바일 화면의 방향과 관련없는 컨트롤의 기본 설정 정보를 지정하고, portrait에는 화면이 세로 상태일 때의 설정, landscape에는 화면이 가로 상태일 때의 설정을 지정하고, options에는 양 방향에 기본으로 적용되는 속성들을 지정한다.

list.setConfig({
    props: {},
    options: {},
    portrait: {},
    landscape: {}
});

화면 방향에 따른 구분 설정이 필요없다면 options 설정으로 충분하다.

Single Row

컨트롤은 기본적으로 최대한 여러 행을 표시하려고 하지만, 한 번에 한 행의 값들만 표시되도록 설정할 수도 있다.

const row_template = {
    template: {
        layout: 'vlinear',
        height: '100%',
        itemsAlign: 'center',
        itemsArrange: 'center',
        children: ['message', 'target'],
        style: { fontSize: '30px' },
    }
};
const list = RealTouch.createListControl(document, "realtouch");

list.setConfig({
    props: {
        templates: { row: row_template }
    },
    options: {
        singleRow: true
    }
});

list.data = RealTouch.createListData("", null, [{
    message: 'Hello',
    target: 'World'
}, {
    message: 'Goodbye',
    target: 'Earth!'
}]);

데이터소스에는 두 행이 존재하지만 첫번째 행 하나만 표시되고 있다. 두 번 째행은 컨트롤을 swipe 제스처로 밀어서 확인할 수 있다.
image-04
template에 대해서는 이어지는 예제에서 설명한다.

Data Source

데이터소스는 컨트롤에 표시할 데이터를 저장하고 관리하는 객체입니다. 데이터소스는 크게 데이터 원본을 저장하는 RtListData, 정렬, 필터링으로 데이터원본의 행 배치를 다르게 구성하는 RtDataView, 둘 이상의 데이터소스를 마스터/디테일 관계로 연결해서 행을 구성하는 RtDataLinkView로 분류된다.
데이터는 필드 구성에 맞게 데이터행 값들이 저장되는데, RtListData에 필드 목록을 설정할 수 있다. 하지만, 간단한 경우 최초 로드하는 데이터의 첫번째 행 값들을 기준으로 필드 목록을 자동 생성한다. 데이터는 데이터소스 객체 생성시 초기값으로 전달할 수 있다. 값의 형태는 기본적으로 json 객체 배열이다.

const json = await(await fetch('../data/samples.json')).json();

list = RealTouch.createListControl(document, 'realtouch');
list.data = RealTouch.createListData("data", {}, json);

CSVTSV 형태의 텍스트 데이터를 로드할 수도 있다.

const csv = await(await fetch('../data/samples.csv')).text();

list = RealTouch.createListControl(document, 'realtouch');
list.data = RealTouch.createListData("data", {}, {
    type: "csv",
    values: csv,
    fieldHeader: 0,
    startRow: 1,
    quoted: true
});

Templates

컨트롤은 데이터행이 표시되는 body 영역 외에 여러 표시 영역으로 구성된다. 대부분의 영역은 '템플릿'으로 표시 형태를 지정한다. 템플릿의 기본 구성은 아래와 같다.

const template = {
    rowProps: {
    },
    vars: {
        nameStyle: {}
    },
    template: {
        layout: 'hlinear',
        children: []
    },
    rowStyle: {
        background: 'yellow',
        color: 'gray',
        checked: {},
        updated: {}
    }
}

rowProps에는 데이터행이나 기타 영역의 높이를 명시적으로 지정한다.

{
    rowProps: {
        minHeight: 30,
        height: 50,
        maxHeight: 100
    }
}

vars에는 템플릿에서 반복적으로 사용되는 값을 정의해서 이름으로 적용할 수 있게 한다. 다른 곳에 사용할 때는 이름 앞에 '--'(double dash)를 붙여 사용한다.

const template = {
    var: {
        'num-style': { color: 'blue', fontWeight: 'bold' }
    },
    template: {
        children: [{
            field: 'age',
            style: '--num-style'
        }, {
            field: 'salary',
            style: '--num-style'
        }]
    }
}

템플릿 본체는 'template' 속성으로 지정되는 최상위 layout을 구성한다. 레이아웃 type과 속성 및 스타일 속성들을 지정하고, children 속성에 자식 layout 및 field들의 배열을 설정한다.

const template = {
    template: {
        type: 'hlinear',
        style: {},
        children: [{
            field: 'name',
        }, {
            field: 'department',
        }]
    }
}

개별 layout에는 width, height를 지정할 수 있지만, 최상위 layout의 크기는 layout의 내용을 참조해서 데이터행이나 섹션이 결정하므로, 크기 관련 속성들을 지정할 필요가 없다.
layout 종류는 아래에 설명된다. 레이아웃 필드는 'field' 속성에 데이터필드명을 지정해서 데이터에 연결되거나, 'value' 속성을 지정해서 상수 값이나 param 값을 표시할 수 있다. 또, 레이아웃 필드에는 width, height 속성을 지정할 수 있다.

{
    children: [{
        field: 'field-name',
    }, {
        value: '${value}'
    }]
}

템플릿 Param

템플릿 param은 '${param;default;format}" 형식으로 지정하는 값으로, 실행시간 동적으로 값이 계산된다. 세미콜론(;)으로 분리되는 세 가지 값을 지정할 수 있는데, 첫째는 param 이름, 두번째는 기본값, 세번째는 문자열로의 변환 형식이다. 두 세번째 값을 생략할 수 있다. 또, '$' 문자가 예약어로 사용되는 경우 '%' 문자들 대신 사용할 수 있다.
템플릿 param은 데이터행을 비롯 템플릿이 사용되는 모든 곳에서 사용될 수 있으면, param의 값은 표시되는 시점에 결정되는데, param이 사용되는 위치에 따라 몇 가지 방식으로 값이 계산되고, 기본적으론느 템플릿의 params 목록에 상수 값이나 콜백 함수로 지정할 수 있다.

{
    template: {
        children: [{
            renderer:  {
                type: 'icon',
                iconSet: 'icons1',
                iconName: '${icon}'
            }
        }]
    },
    params: {
        icon: args => {
            switch (args.row % 4) {
                case 0:
                    return 'google';
                case 1:
                    return 'slack';
                case 2:
                    return 'git';
                case 3:
                    return 'admob';
            }
        }
    }
}

위의 params 외에 템플릿을 사용하는 영역의 모델마다 param 값을 제공하는 속성들이 존재한다.

Stock Params

데이터행이나 리스트 헤더 등의 영역은 라이브러리 수준에서 몇가지 값을 param으로 제공한다. 또, 레이아웃 필드의 value 속성에 데이터필드를 param으로 지정할 수도 있다.

{
    template: {
        children: [{
            value: '${@field-name}'
        }]
    }
}

Layouts

6개의 기본 layout과 직접 html로 layout을 구성하는 방식을 사용할 수 있다.

HLinear Layout

자식 layout 및 field들을 순서대로 수평 배치한다.

template: {
    layout: 'hlinear',
    children: [{
        field: 'message',
        style: { backgroundColor: 'lightgray' }
    }, {
        field: 'target',
        style: { backgroundColor: '#0088ff', color: 'white', fontSize: '30px' }
    }, {
        field: 'distance',
        style: { backgroundColor: 'yellow', border: '1px solid green', padding: '4px'}
    }],
    style: { fontSize: '20px' },
}

image-05

VLinear Layout

자식 layout 및 field들을 순서대로 수직 배치한다.

template: {
    layout: 'vlinear',
    children: [{
        field: 'message',
        style: { backgroundColor: 'lightgray' }
    }, {
        field: 'target',
        style: { backgroundColor: '#0088ff', color: 'white' }
    }, {
        field: 'distance',
        style: { backgroundColor: 'yellow', border: '1px solid green', padding: '4px'}
    }],
    style: { fontSize: '18px' },
}

image-06

Frame Layout

자식 layout 및 field들이 명시직으로 지정된 위치에 표시된다.

const row_template = {
    template: {
        layout: 'frame',
        children: [{
            field: 'message',
            left: 10,
            top: 10,
            style: { backgroundColor: 'lightgray' }
        }, {
            field: 'target',
            style: { backgroundColor: '#0088ff', color: 'white' }
        }, {
            field: 'distance',
            right: 10,
            bottom: 10,
            style: { backgroundColor: 'yellow', border: '1px solid green', padding: '4px'}
        }],
        style: { background: '#00ff8840', fontSize: '18px', border: '1px dashed gray' },
    },
    rowProps: {
        height: 100
    }
};

image-07

자식들의 left, right, top, bottom 속성으로 위치를 지정할 수 있다.

Stack Layout

자식들 중 하나만 표시하고, 나머지는 감춘다. IRtStackLayout.activeChild 속성으로 표시할 자식의 IRtLayoutChild.id를 지정한다.

const row_template = {
    template: {
        layout: 'stack',
        activeChild: '${active;target}',
        children: [{
            id: 'message',
            field: 'message',
            style: { backgroundColor: 'lightgray' }
        }, {
            id: 'target',
            field: 'target',
            style: { backgroundColor: '#0088ff', color: 'white' }
        }, {
            id: 'distance',
            field: 'distance',
            style: { backgroundColor: 'yellow', border: '1px solid green', padding: '4px'}
        }],
        style: { background: '#00ff8840', fontSize: '18px', border: '1px dashed gray' },
    },
    rowProps: {
        height: 60
    },
    params: {
        active: arg => {
            switch (arg.row % 3) {
                case 0: return 'message';
                case 1: return 'target';
                default: return 'distance';
            }
        }
    }
};

image-08

Form Layout

이름(label)과 값(field)를 한 줄에 표시하고, 각 줄의 위치를 동기화 시키는 형태로 항목들을 배치한다. 주로 Single Row나 입력 페이지 등에서 편집기와 함께 사용된다.

{
    layout: 'form',
    labelWidth: '30%',
    labelStyle: {
        textAlign: 'right',
        fontWeight: 'bold'
    },
    children: [{
        field: 'message',
        label: '메시지:',
        editor: { maxLength: 30 }
    }, {
        field: 'target',
        label: 'Target:',
        editor: { placeholder: '대상 입력' }
    }, {
        field: 'distance',
        label: '거리:',
        editor: { type: 'number' }
    }],
}

image-09

Html Layout

Html을 직접 작성하여 내용을 직접 구성한다. Html element는 컨트롤 컨테이너 아래 포함시킬 수 있으며, 컨트롤 컨테이너에 'rtc-renderers' selector를 갖는 div를 추가하고, layout으로 사용할 내용을 그 div의 자식들로 표함시켜야 한다. 또, 템플릿에 지정할 때 필요하므로 반드시 id 속성이 지정되어야 한다.

<body>
    <div id="realtouch">
        <div class="rtc-renderers">
            <div id="row">
                <div><span style="font-size:17px;font-weight:bold;color:#555;">${@OILSTATN_NM}</span></div>
                <div><span style="font-size:14px;color:#777;">${@LOCPLC_ROADNM_ADDR}</span></div>
            </div>
        </div>
    </div>
</body>
const row_template = {
    template: {
        type: 'html',
        domid: 'row',
    },
    rowStyle: {
        checked: {
            backgroundColor: '#0088ff20'
        }
    }
};

위 방식 외에 html 태그들을 직접 템플릿의 속성으로 지정하는 방법도 있다.

const row_template = {
    template: {
        html: '<div id="row"><div><span style="font-size:17px;font-weight:bold;color:#559;">${@OILSTATN_NM}</span></div><div><span style="font-size:14px;color:#777;">${@LOCPLC_ROADNM_ADDR}</span></div></div>'
    },
    rowStyle: {
        checked: {
            backgroundColor: '#0088ff20'
        }
    }
};

템플릿 root에 'html' 속성이 있으면 Html Layout이 생성된다.

Renderers

레이아웃 필드 영역은 렌더러가 다양한 방식으로 표시한다.

{
    template: {
        children: [{
            field: 'STATE',
            renderer: {
                type: 'shape',
                shapeSize: 20,
                style: {
                }
            }
        }]
    }
}

다양한 렌더러가 제공되면 특별히 지정하지 않으면 텍스트 렌더러가 사용된다. Renderers 도움말 페이지를 참조한다.

Editors

데이터필드의 값을 입력해야 하는 경우 렌더러 대신 편집기를 표시해야 한다.

{
    template: {
        layout: 'form',
        children: [{
            label: '이 름',
            editor: {
                type: 'text'
            }
        }, {
            label: '남여',
            editor: {
                type: 'check'
            }
        }]
    }
}

편집 페이지폼 패널 등에서 필드 값을 입력할 때 사용되는 편집기들을 제공한다. Editors 도움말 페이지를 참조한다.

수평 모드

리스트 컨트롤은 기본적으로 데이터행들을 위에서 아래로 수직 배치하는데, orientation 속성을 지정해서 수평으로 행들이 배치되게 할 수 있다.

const config = {
    options: {
        orientation: 'horizontal'
    }
}

만일, 가로 상태일 때만 수평으로 배치하고 싶다면,
const config = {
    landscape: {
        orientation: 'horizontal'
    }
}

Render Mode

리스트 컨트롤은 기본적으로 현재 표시되는 데이터행들만 html을 생성하는 가상 리스트뷰이다. 즉, 연결된 데이터소스에 수 만 행이 존재해도 디바이스 창에 10행만 표시된다면, 10행을 위한 html만 생성된다. 하자만, 때로 모든 행에 대한 html을 생성해야 하는 경우도 있을 수 있는데, 컨트롤 생성 시 이 방식을 지정할 수 있다.

list = RealTouch.createListControl(document, 'realtouch', 'pre');
// 혹은
list = RealTouch.createListControl(document, 'realtouch', 'full');

'full' 모드는 데이터행 수에 따라 모든 행이 표시되도록 컨트롤의 크기 자체를 변경시킨다.

Row Bar

데이터행의 양쪽 끝을 활용해서 행의 상태를 표시하거나 행과 관련된 action을 실행하는 버튼 등을 표시할 수 있다. RowBar는 기본적으로 각 행의 왼쪽에 데이터행 번호나 행 상태 등을 나타내는 이미지나 shape를 표시한다. options.rowBar 속성으로 설정한다.

{
    options: {
        rowBar: {
            visible: true,
            display: 'order',
            order: {
                suffix: '.',
                style: { fontSize: '19px', color: '#777' }
            }
        }
    }
}

Edit Bar

EditBar는 기본적으로 각 행의 오른쪽에 행과 관련된 action을 실행하는 버튼을 표시한다. 행 '삭제', '수정', '삭제', '정보' 등은 기본 액션으로 지정할 수 있다. options.editBar 속성으로 설정한다.

{
    options: {
        editBar: {
            visible: true,
            action: 'delete',
            delete: {
                label: '삭제',
                confirmMessage: '삭제할까요?'
            }
        }
    }
}

Grouping

데이터행들을 특정 필드나 필드들의 값들을 기준으로 묶어서 표시할 수 있다. 또, 데이터링크뷰인 경우 마스터행 기준으로 구별해서 표시할 수 있다.

// 부서별로 grouping
list.rowGroupBy(['DEPT']);

물론 먼저 해당 필드를 기준으로 데이터가 정렬돼야 같은 그룹이 중복되지 않는다.

const dv = data.createView().sort(['DEPT']);
list.data = dv;
list.rowGroupBy(['DEPT']);

컨트롤에 설정된 데이터가 데이터링크뷰일 때 그룹핑은 마스터/디테일 형태와 그룹핑 UI를 제공한다. 어떤 마스터 수준에서 그룹핑할 것인 지, 마스터의 footer를 표시할 것인 지 등은 options.dataGroup에서 설정한다.

list.dataGroupBy({});

See Also

RtListControl