이번에는 ExtJS5에서 제공되는 차트컴포넌트를 구현해보도록 하겠습니다.
예전 ExtJS강좌의 첫번째 포스팅부분에서 extjs gpl 버전 다운받으신다음
해당 압축해제 파일들을 삭제하지 말아달라고 요청드렸었죠?
2014/10/18 - [웹개발강좌/ExtJS] - ExtJS 강좌 - ExtJS5를 이용한 설치 및 연동하기 편
이제는 차트 구현을 하기위해서는
이미 빌드되어있는 폴더 하나를 프로젝트 경로에 추가하도록 하겠습니다.
"/extjs-5.0.x/build/packages/" 디렉토리를 보시면
다음과 같은 2가지 종류의 차트관련 폴더를 확인 하실 수 있으실 겁니다.
2종류의 차트의 차이점을 확인한 결과
ExtJS5이전버전인 ExtJS4.x 버전에 사용가능한 차트를 "ext-charts" 디렉토리에 빌드해놓았고
ExtJS5부터 신규로 빌들된 차트는 "sencha-charts" 디렉토리내에 빌드를 해놓았습니다.
확인결과 차트호출관련 xtype 만 별도로 차이를 두었을뿐 크게 차이가 나지는 않는것같습니다.
저희는 ExtJS5로 꾸준히 진행을 해왔으므로
"sencha-charts"디렉토리를 기존 ExtJS 테마들을 넣어놓은 디렉토리내에 INCLUDE 하도록 하겠습니다.
그럼 차트관련 JS파일을 기존 ExtJS JS/CSS 파일 INCLUDE되어있는
HTML/JSP/PHP 파일내에 INCLUDE 하도록 합니다.
<script type="text/javascript" src="/extjs/sencha-charts/build/sencha-charts.js"></script>
지원하는 차트 종류는 어마어마하게 많지만 자주 사용되는 일부차트컴포넌트만
일부 샘플로 제작하여 맛보기삼아서 만들어보도록 하겠습니다.
ExtJS의 차트컴포넌트 종류는 'cartesian' 타입과 'polar' 타입으로 나누어 볼 수 있겠는데
이번 포스팅은 'cartesian' 종류의 컴포넌트를 다루어 보도록 하겠습니다.
cartesian 차트란?
X/Y 좌표 두방향을 갖는 직교좌표입니다.
flipXY 속성으로 그래프 방향변경이 가능합니다.
샘플화면은 티스토리에서 기본적으로 제공하는 방문자수 그래프 데이터를 기준으로 예를 들어볼까 합니다
전체 샘플코드에서 동일한 데이터 스토어는 변수에 담아서 사용할 예정이므로
다음처럼 Ext.onReady 내에 정의해주세요
var chartStore = Ext.create('Ext.data.Store',{ fields : ['date','count'], data : [ {date : '10',count : 305 }, {date : '11',count : 335 }, {date : '12',count : 329 }, {date : '13',count : 360 }, {date : '14',count : 298 }, {date : '15',count : 77 }, {date : '16',count : 99}, {date : '17',count : 130 } ] })
차트컴포넌트 관련코드 또한 Ext.onReady안에 정의해주세요
Ext.create('Ext.panel.Panel', { renderTo: Ext.getBody(), width: 650, height: 500, title : '방문자통계', layout: 'fit', items: [ { xtype: 'cartesian', //위치 axes: [{ type: 'numeric', position: 'left', minimum: 0 }, { type: 'category', position: 'bottom' }], //차트타입 series: { type: 'bar', axis: 'left', xField: 'date', yField: 'count', //그래프 내에 출력할 값 label: { field: 'count', display: 'insideEnd' } }, //데이터 출력 store: chartStore } ] });
위에 보게되면 ExtJS 4.x 버전에서는 xtype : 'chart' 였었던 컴포넌트가 'cartesian' 이라고 변경이 되었습니다.
그리고 axes / series / store 속성은
차트컴포넌트에서 패키지로 따라다니는 속성들이라고 생각하시면 되겠습니다.
'axes' 속성의 경우, 가로/세로의 축을 정의해주는 속성이며
'series' 속성의 경우는 차트컴포넌트의 타입 및 각 화면에 출력하고자 하는 값들의 정의를 나타내는 속성입니다.
Ext.create('Ext.panel.Panel', { renderTo: Ext.getBody(), width: 650, height: 500, title : '방문자통계', layout: 'fit', items: [ //가로형 막대차트컴포넌트 { xtype: 'cartesian', flipXY: true, //위치 axes: [{ type: 'numeric', position: 'bottom', minimum: 0 }, { type: 'category', position: 'left' }], //차트타입 series: { type: 'bar', xField: 'date', yField: 'count', //그래프 내에 출력할 값 label: { field: 'count', display: 'insideEnd' } }, //데이터 출력 store: chartStore } ] });
가로형 막대그래프는 세로형과 다른점이 있다면
축설정 axes 속성에 position이 변경되었으며 flipXY 속성을 TRUE로 지정을 해주셔야
가로형으로 차트출력이 가능합니다.
Ext.create('Ext.panel.Panel', { renderTo: Ext.getBody(), width: 650, height: 500, title : '방문자통계', layout: 'fit', items: [ //라인형 차트 { xtype: 'cartesian', //위치 axes: [{ type: 'numeric', position: 'left', minimum: 0 }, { type: 'category', position: 'bottom' }], series: [{ type: 'line', xField: 'date', yField: 'count', //결과값을 그래프에 출력하기 위한 속성 label: { field: 'count', display: 'over' } }], //데이터 출력 store: chartStore } ] });
선형 그래프는 맨위에 티스토리 통계 이미지를 출력한 그래프와 동일한 화면구성을 해주는 그래프입니다.
"series" 속성의 type이 'line'으로 변경된 점과 label 속성으로 그래프에 출력시켜준 속성이 변경 혹은 추가되었습니다.
위와같이 출력이 되었으나 화면이 넘쳐서 label 부분에 대한
숫자값이 잘려보이는 현상이 발생합니다.
이 간격을 약간 조정을 해주기 위하여 "insetPadding","innerPadding" 속성을
다음처럼 xtype: 'cartesian', 다음라인에 추가해주도록 합니다
insetPadding: 40, innerPadding: { left: 40, right: 40 },
위처럼 전체적으로 그래프사이즈가 줄어든 것을 확인하였습니다.
Ext.create('Ext.panel.Panel', { renderTo: Ext.getBody(), width: 650, height: 500, title : '방문자통계', layout: 'fit', items: [ { xtype: 'cartesian', //============간격조정============ insetPadding: 40, innerPadding: { left: 40, right: 40 }, //============간격조정============ //위치 axes: [{ type: 'numeric', position: 'left', minimum: 0 }, { type: 'category', position: 'bottom' }], series: [{ type: 'scatter', xField: 'date', yField: 'count', tooltip: { trackMouse: true, renderer: function(storeItem, item) { this.setHtml(storeItem.get('date') + '일 : ' + storeItem.get('count') + ' 명'); } } }], //데이터 출력 store: chartStore } ] });
분산형그래프 코드에서 기존 그래프 컴포넌트들과 차이라면
'series' 타입이 'scatter'이라는 점과 tooltip 속성이 추가되었다는 점입니다.
툴팁속성은 출력된 분산형 그래프에 마우스오버를 하게되면
해당 그래프에 대한 데이터 결과값이 툴팁처럼 출력이 되어 나타나는 속성입니다.
※ 툴팁은 타그래프에서도 사용가능한 기능입니다.
'cartesian' 타입의 마지막 샘플인 "영역형 그래프"에 대한 샘플코드를 보도록 하겠습니다.
Ext.create('Ext.panel.Panel', { renderTo: Ext.getBody(), width: 650, height: 500, title : '방문자통계', layout: 'fit', items: [ { xtype: 'cartesian', //============간격조정============ insetPadding: 40, //============간격조정============ //위치 axes: [{ type: 'numeric', position: 'left', minimum: 0 }, { type: 'category', position: 'bottom' }], series: [{ type: 'area', xField: 'date', yField: 'count', //툴팁 tooltip: { trackMouse: true, renderer: function(storeItem, item) { this.setHtml(storeItem.get('date') + '일 : ' + storeItem.get('count') + ' 명'); } } }], //데이터 출력 store: chartStore } ] });
지금까지 xtype이 'cartesian'인 차트 종류에 대하여 알아보았습니다.
다음 장에는 간단하게 xtype이 'polar'인 차트에 대하여 포스팅 해보도록 하겠습니다 .^^
by 개발로짜
ExtJS 강좌 - Sencha CMD로 ExtJS 구조 생성하여 연동테스트 해보기 (1) | 2014.11.24 |
---|---|
ExtJS 강좌 - ExtJS5의 polar 타입 차트그래프 간단하게 알아보기 (0) | 2014.11.18 |
ExtJS 강좌 - Ajax 비동기 통신에 대하여 알아보자 (0) | 2014.11.13 |
ExtJS 강좌 - DATAVIEW를 이용하여 데이터 목록 출력해보기 (3) | 2014.11.12 |
ExtJS 강좌 - 클릭이벤트를 적용하여 탭컴포넌트 동적으로 추가하기 (12) | 2014.11.08 |
질문) 팝업창에서 데이터 처리후 해당값을 부모창에 넘겨주는 것을 만드는데요.
공통팝업이다보니, 호출이 필요한 화면에서는 호출될 동일한 메소드명을 만들고 해당 팝업은 그냥 그 메소드명을 호출하는것으로 처리하려는데,
해당 메소드들을 못찾습니다..
어떻게 해야 팝업 윈도우에서 부모 창의 메소드를 호출할수 있을까요?
(--> 팝업창의 grid 선택하고 적용버튼 누름, 해당 grid 를 넘겨서.. 선택된 row 의 값들을 각 화면에서 처리하는것입니다.)
답변) 위에 대한 내용만으로는 어떠한 결과를 원하시는지 이해가 되지 않아 2가지 경우를 예를들어 답변드리도록 하겠습니다.
<div id="panel1"></div> <div id="panel2"></div>
제일먼저 임의의 폼패널 2개를 생성하기 위하여 각각 div 2개를 작성하였습니다.
Ext.onReady(function(){ Ext.create("Ext.form.Panel",{ renderTo : document.getElementById("panel1"), title : '주소검색 샘플예제(1)', width: 600, items : [{ fieldLabel: '우편번호', name : 'zipcode', xtype : 'textfield', },{ fieldLabel: '기본주소', name : 'default_address', xtype : 'textfield' },{ fieldLabel: '상세주소', name : 'detail_address', xtype : 'textfield' }], fbar : [{ xtype : 'button', text : '검색', handler : function(btn){ if(Ext.getCmp("addrWindow") == undefined) { showWindow(btn); } } }] }); Ext.create("Ext.form.Panel",{ renderTo : document.getElementById("panel2"), title : '주소검색 샘플예제(2)', width: 600, items : [{ fieldLabel: '우편번호', name : 'zipcode', xtype : 'textfield', },{ fieldLabel: '기본주소', name : 'default_address', xtype : 'textfield' },{ fieldLabel: '상세주소', name : 'detail_address', xtype : 'textfield' }], fbar : [{ xtype : 'button', text : '검색', handler : function(btn){ if(Ext.getCmp("addrWindow") == undefined) { showWindow(btn); } } }] }) }) function showWindow(btn){ Ext.create('Ext.window.Window',{ id : 'addrWindow', width : 700, height : 300, title : '주소검색창', items : [{ xtype : 'grid', columns : [{ text : '우편번호', flex : 1, dataIndex : 'zipcode' },{ text : '주소', flex : 1, dataIndex : 'address' }], store : Ext.create("Ext.data.Store",{ fields : ['zipcode','address'], data : [{ zipcode : '111-222', address : '서울 종로구 삼청동' },{ zipcode : '333-444', address : '경기 안양시 만안동' },{ zipcode : '333-454', address : '경기 광주시 태전종' }], proxy : { type : 'memory' } }) }], fbar : [{ xtype : 'button', text : '적용', handler : function(btn2){ var gridObj = Ext.getCmp("addrWindow").down("grid"); var selectgrid = gridObj.getSelectionModel().getSelection()[0]; var zipcode = selectgrid.get("zipcode"); var address = selectgrid.get("address"); var zipcodeObj = btn.up("form").down("textfield[name=zipcode]") var addressObj = btn.up("form").down("textfield[name=default_address]") //부모창 호출함수 setPanel(gridObj,zipcode,address,zipcodeObj,addressObj); } }] }).show(); } function setPanel(obj,zipcode,address,parent_zipcode,parent_address){ parent_zipcode.setValue(zipcode); parent_address.setValue(address); obj.up("window").close(); }
showWindow() 함수
그리드패널을 자식컴포넌트로 가지는 윈도우 컴포넌트를 폼패널의 검색버튼 클릭시 화면에 출력시키며
윈도우화면의 적용버튼 클릭시 선택된 그리드 ROW의 각 값을 setPanel 함수로 보내주는 기능을 가진
컴포넌트출력 + 기능함수입니다.
setPanel() 함수
각 선택된 값들을 폼패널의 입력컴포넌트에 대입을 하며
윈도우창을 CLOSE 해주는 기능을 가진 함수입니다.
실행을 해보도록 하겠습니다.
우선 요청 주셨던 함수 하나로 검색버튼 위치에 따라
그리드내에 선택값이 해당 폼필드로 적용되는것을 확인 할 수 있습니다.
<form action="/전송URL" method="post" name="frm"> 우편번호 : <input type="text" name="zipcode" /><input type="button" onclick="popuptest()" value="검색"/><br/> 기본주소 : <input type="text" name="default_address" /><br/> </form>
위와같이 일반 HTML 소스코드 작성후 FUNCTION 2개를 SCRIPT 태그내에 정의합니다.
function popuptest(){ window.open("/pop.html","test","'scrollbars=yes,toolbar=yes,resizable=yes,width=500,height=500,left=0,top=0"); } function setadderss(zipcode,address) { document.frm.zipcode.value = zipcode; document.frm.default_address.value = address; }
window.open으로 호출해준 pop.html 페이지다 하단 스크립트 코드를 적용합니다.
※ 부모창에는 ExtJS 연동을 할필요가 없으므로 ExtJS 관련 CSS 및 JS 파일을 INCLUDE 할 필요가 없습니다.
대신 WINDOW.OPEN 호출한 pop.html 파일에는 ExtJS관련 파일들을 include 해주어야 합니다.
Ext.onReady(function(){ Ext.create('Ext.panel.Panel',{ renderTo : Ext.getBody(), title : '그리드샘플', width : 500, height : 500, items : [{ xtype : 'grid', columns : [{ text : '우편번호', flex : 1, dataIndex : 'zipcode' },{ text : '주소', flex : 1, dataIndex : 'address' }], store : Ext.create("Ext.data.Store",{ fields : ['zipcode','address'], data : [{ zipcode : '111-222', address : '서울 종로구 삼청동' },{ zipcode : '333-444', address : '경기 안양시 만안동' },{ zipcode : '333-454', address : '경기 광주시 태전종' }], proxy : { type : 'memory' } }) }], fbar : [{ xtype : 'button', text : '적용', handler : function(btn){ var gridObj = btn.up("panel").down("grid"); var selectgrid = gridObj.getSelectionModel().getSelection()[0]; var zipcode = selectgrid.get("zipcode"); var address = selectgrid.get("address"); opener.setadderss(zipcode,address); self.close(); } }] }) })
실행결과를 보도록 하겠습니다.
위처럼 정상적으로 팝업창의 선택 그리드 ROW 값이 부모입력화면에 대입이 되었습니다.
by 개발로짜
"ExtJS_OS" 님께서 질문주신 dataview 관련 답변 코드 입니다. (0) | 2014.11.14 |
---|
우선 mybatis와 ibatis에서는 동적태그를 기본적으로 지원을 합니다.
즉, 프로시저로 짜여져 있는 로직을 동적태그를 사용하여 쿼리로 변경할 수 있습니다.
장점이 있을수도 있지만 자칫 잘못 사용하면 큰 문제를 일으킬수 있다는 단점이있을수 있다는...
양날의 칼날과 같다는것만 알아두시면 되겠습니다.
isNull : "널일경우"
isNotNull : "널이아닐경우"
isEmpty : "공백일경우"
isNotEmpty : "공백이아닐경우"
isGreaterTan : ">"
isGreaterEqual : ">="
isLessThan : "<"
isLessEqual : "<="
isEqual : "=="
isNotEqual : "!="
if : 단일조건문
choose when otherwise : 다중조건문
위와같이 각 mybatis(ibatis) 별 동적태그를 지원합니다.
ibatis에 비해 mybatis의 비교문태그가 간단해졌습니다.
ibatis에서 지원되는 태그들 if문과 choose문만을 이용하여 비교가 가능해 진것이죠.
일반 자바코드와 ibatis/mybatis 별로 비교문 예를 들어보도록 하겠습니다.
if(stringProperty == null) { // code here }
<!--ibatis --> <isNull property="stringProperty"> 조건문 </isNull> <!--mybatis--> <if test="stringProperty == null"> 조건문 </if>
if(stringProperty != null) { // code here }
<!--ibatis --> <isNotNull property="stringProperty"> 조건문 </isNotNull> <!--mybatis(1)--> <if test="stringProperty != null"> 조건문 </if> <!--mybatis(2)--> <choose> <when test="stringProperty == null"> NULL일경우 조건문 </when> <otherwise> NULL이 아닐경우 조건문 </otherwise> </choose>
if(stringProperty.equals("")) { //code here }
<!--ibatis--> <isEmpty property="stringProperty"> 조건문 </isEmpty> <!--mybatis--> <if test="stringProperty == ''"> 조건문 </if>
if(!stringProperty.equals("")) { //code here }
<!--ibatis--> <isNotEmpty property="stringProperty"> 조건문 </isNotEmpty> <!--mybatis(1)--> <if test="stringProperty != ''"> 조건문 </if> <!--mybatis(2)--> <choose> <when test="stringProperty == ''"> 공백일경우 조건문 </when> <otherwise> 공백 아닐경우 조건문 </otherwise> </choose>
if(numberProperty > 5) { //code here }
<!--ibatis--> <isGreaterThan property="numberProperty" compareValue="5"> 5보다 클경우 조건문 </isGreaterThan> <!--mybatis--> <if test='id > 5'> 5보다 클경우 조건문 </if>
if(numberProperty >= 5) { //code here }
<!--ibatis--> <isGreaterEqual property="numberProperty" compareValue="5"> 5보다 크거나같을경우 조건문 </isGreaterEqual> <!--mybatis--> <if test='id >= 5'> 5보다 크거나같을경우 조건문 </if>
if(numberProperty < 5) { //code here }
<!--ibatis--> <isLessThan property="numberProperty" compareValue="5"> 5보다 작을경우 조건문 </isLessThan> <!--mybatis--> <if test='id < 5'> 5보다 작을경우 조건문 </if>
if(numberProperty <= 5) { //code here }
<!--ibatis--> <isLessEqual property="numberProperty" compareValue="5"> 5보다 작거나같을경우 조건문 </isLessEqual> <!--mybatis--> <if test='id <= 5'> 5보다 작거나같을경우 조건문 </if>
if(stringProperty.equals("title")) { //code here }
<!--ibatis--> <isEqual property="stringProperty" compareValue="title"> stringProperty 속성값이 "title"일 경우 </isEqual> <!--mybatis--> <if test='stringProperty == "title"'> stringProperty 속성값이 "title"일 경우 </if>
if(!stringProperty.equals("title")) { //code here }
<!--ibatis--> <isNotEqual property="stringProperty" compareValue="title"> stringProperty 속성값이 "title"이 아닐경우 </isNotEqual> <!--mybatis--> <if test='stringProperty != "title"'> stringProperty 속성값이 "title"이 아닐경우 </if>
마지막으로 다중 조건체크에 대한 예를 들어보도록 하겠습니다.
if(stringProperty != null && !stringProperty.equals("")) { //code here }
<!--ibatis--> <isNotNull property="stringProperty"> <isNotEmpty property="stringProperty"> 조건문 </isNotEmpty> </isNotNull> <!--mybatis--> <if test='stringProperty != null and stringProperty == ""'> stringProperty 속성값이 "title"이 아닐경우 </if>
위처럼 ibatis의 경우에는 태그안에 태그를 여러번 넣어줘야해서 솔직히 번거롭습니다.
하지만 mybatis는 JSTL과 동일한 문법으로 사용이 가능하여
편하게 비교문을 다중조건을 주어서 사용할 수 있습니다.
다만 다른 점이 있다면
&& 문을 and || 문을 or 로 작성 해주셔야 합니다.
by 개발로짜
Spring3 + Mybatis 연동 후 DBMS 종류별(MySQL,MSSQL,Oracle) 데이터 insert 후 시퀀스 가져오기 (0) | 2014.11.19 |
---|---|
mybatis와 ibatis 반복문 비교하기(foreach vs iterate) (0) | 2014.11.17 |