그리드패널에서 사용되는 스토어는 "Ext.data.Store" 를 사용하지만
트리패널에서 사용되는 스토어는 "Ext.data.TreeStore"를 사용합니다.
사용되는 데이터스토어가 다르고 스토어들의 사용법 또한 살짝(?) 다릅니다.
proxy 타입이 "memory" 기준으로 설명을 드리자면
data : [{ blogger_id : 'guklife', blogger_name : '국이', blogger_url : 'guklife.tistory.com' },{ blogger_id : 'hellogk', blogger_name : '개발로짜', blogger_url : 'hellogk.tistory.com' }]
위처럼 json array 하나에 여러개의 json object를 정의하는 구조인 1:n 형식입니다.
그렇다면 트리구조일 경우에는 데이터 출력을 위해 다음과 같은 구조로 정의해줍니다.
root : { text : '1depth', expanded : true, children: [{ text:'2depth(1)', expanded: true, children:[{ text:'3depth', leaf : true }] },{ text:'2depth(2)', leaf : true }] }
위 구조는 ajax 비동기 통신할때도 동일한 구조로 진행이 되어야 합니다.
각각 설명을 해보자면
① root속성부터 트리컴포넌트 1depth 노드의 시작이다.
② 자식노드를 출력하기 위해서는 children 속성내에 json배열 형식으로 각 object 를 선언한다.
※ 속성에 알아봐야 할 중요 key 설명
text : 트리구조 출력시 화면에 노출되는 문자열(필수)
expanded : true/false boolean 형식의 값을 정의한다.
true일 경우 - 자식노드 확장
false일 경우 - 자식노드가 확장을 해놓지 않음
leaf : 마지막 노드인지 구분을 위한 속성값
역시 true/false boolean 형태
expanded 속성과 leaf 속성을 구분하여 다음의 case별로 적용해주시면 되실거 같습니다.
1. 더이상의 자식노드가 없다면? expanded 속성 생략 + leaf : true
이 경우 childrend 속성도 생략해야 하겠죠?
2. 자식노드가 존재하지만 확장을 시켜놓지 않을것이다? expanded : false
3. 자식노드가 존재하며 확장을 시켜놓겟다? expanded : true
위 3가지를 꼭 기억해주도록 합니다.
Ext.onReady(function(){ Ext.onReady(function(){ Ext.create('Ext.tree.Panel',{ renderTo : Ext.getBody(), store : Ext.create('Ext.data.TreeStore',{ root : { text : '1depth', expanded : true, children: [{ text:'2depth(1)', expanded: true, children:[{ text:'3depth', leaf : true }] },{ text:'2depth(2)', leaf : true }] }, proxy : { type : 'memory' } }) }) });
위처럼 단순하게 트리컴포넌트를 생성해보았습니다.
실행결과를 확인해 보도록 합니다.
위처럼 트리구조로 목록이 출력되었습니다.
다음으로 proxy 타입이 'ajax'인 비동기방식으로 서버통신 후
json 객체로 트리노드를 동적으로 출력해보도록 하겠습니다.
이번 json response 작업 역시 json-simple 라이브러리를 이용하여 진행하였습니다.
2014/10/06 - [코드저장소/java] - JSON 라이브러리를 이용하여 object생성과 문자열을 object형으로 변환해보기
상단 코드중 children 속성을 ajax call 하여 json object로 받을 예정입니다.
proxy 사용방법은 기존 그리드 ajax 와 동일한 구조입니다.
일부 변경된 스크립트 코드는 다음과 같습니다.
Ext.onReady(function(){ Ext.create('Ext.tree.Panel',{ renderTo : Ext.getBody(), store : Ext.create('Ext.data.TreeStore',{ root : { text : '1depth', expanded : false }, proxy : { type : 'ajax', api: { read : '/tree_result.jsp' }, reader: { type: 'json', rootProperty: 'children' } } }) }) });
root 속성의 expanded 값을 false로 정의하였습니다.
트리패널에서는 서버통신이 이루어지는 경우는
트리노드가 확장(expanded : true)이벤트가 발생할때 호출되기 때문에
눈으로 확인해보고자 false로 지정하였습니다.
true로 줄경우 onload 되자마자 바로 트리패널의 children을 ajax call을합니다.
위와같이 작업하였다면 서버 페이지 코드를 작성해보도록 합니다.
JSONObject jsonTreeRootObject = new JSONObject(); JSONArray jsonArray = new JSONArray(); JSONObject jsonTreeObject = null; JSONArray jsonTreeChildrenArray = new JSONArray(); JSONObject jsonTreeChildrenObject = null; jsonTreeObject = new JSONObject(); jsonTreeObject.put("text", "2depth(1)"); jsonTreeObject.put("leaf", true); jsonArray.add(jsonTreeObject); jsonTreeObject = new JSONObject(); jsonTreeObject.put("text", "2depth(2)"); jsonTreeObject.put("expanded", true); jsonTreeChildrenObject = new JSONObject(); jsonTreeChildrenObject.put("text","3depth(1)"); jsonTreeChildrenObject.put("leaf",true); jsonTreeChildrenArray.add(jsonTreeChildrenObject); jsonTreeChildrenObject = new JSONObject(); jsonTreeChildrenObject.put("text","3depth(2)"); jsonTreeChildrenObject.put("leaf",true); jsonTreeChildrenArray.add(jsonTreeChildrenObject); jsonTreeObject.put("children",jsonTreeChildrenArray); jsonArray.add(jsonTreeObject); jsonTreeRootObject.put("success", true); jsonTreeRootObject.put("children", jsonArray); response.setContentType("text/plain; charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.print(jsonTreeRootObject); pw.flush(); pw.close();
json 파싱코드가 기존 작업보다 상당히 길어지고 구조또한 복잡해진거 같죠?
트리의 json object는 depth 구조로 작업을 해야하기 때문입니다.
다음 구조를 보시면 이해가 되실겁니다.
추가 자식노드가 존재하는 json object에 children key값으로
json array 객체를 담는구조가 되어야합니다.
실행을 해보도록 하겠습니다.
정상적으로 ajax call이 이루어지면서 json object 데이터를 화면에 출력이 되었습니다.
트리패널을 ajax call할때 depth별 구조를 잘 잡아 주어야 하므로 json 파싱작업때 주의해주세요!!
트리패널 ajax 호출 시 expand/collapse 이벤트가 한번만 발생하고 이후 동작이 되지 않을경우
proxy속성의 동일 depth에 animate : false 속성을 추가해주도록 합니다.
by 개발로짜
ExtJS 강좌 - 클릭이벤트를 적용하여 탭컴포넌트 동적으로 추가하기 (12) | 2014.11.08 |
---|---|
ExtJS 강좌 - 마우스우클릭으로 contextmenu(컨텍스트메뉴) 띄워보기 (0) | 2014.11.08 |
ExtJS의 그리드패널 reconfigure함수를 적용하여 컬럼 및 데이터 재설정하기 (0) | 2014.11.05 |
ExtJS 강좌 - 그리드패널에 페이징툴바를 적용하여 페이징 목록 출력하기 (10) | 2014.11.03 |
ExtJS 강좌 - 그리드패널을 출력시키기 위하여 이해를 한 후 출력시켜보자 (0) | 2014.11.03 |
이번 강좌의 내용은 존재하는 그리드패널에 대한 컬럼 및 데이터를
재설정 할경우를 위하여 포스팅해보도록 하겠습니다.
그리드패널에서 제공되는 reconfigure함수를 사용하면 재설정이 가능합니다.
그리드객체.reconfigure(신규데이터스토어,신규데이터모델);
한번 샘플코드를 이용하여 이해를 돕도록 해보겠습니다.
데이터스토어와 데이터모델을 각 2개씩 생성하여 변수에 담도록 하겠습니다.
이유는 초반에 그리드에 출력을위한 원본데이터와 reconfigure함수를 적용하여
컬럼 재설정을 위한 변경데이터 이 2가지를 다룰때 필요하기 때문입니다.
var original_store = Ext.create("Ext.data.Store",{ //기존코드에 추가된 부분 fields : ['original_1','original_2'], proxy : { type : 'memory' }, data : [{ original_1 : '원본_데이터1-1', original_2 : '원본_데이터1-2' },{ original_1 : '원본_데이터2-1', original_2 : '원본_데이터2-2' }] }); var original_model = [{ text : '컬럼1', flex : 1, dataIndex : 'original_1' },{ text : '컬럼2', flex : 1, dataIndex : 'original_2' }]; var reconfigure_store = Ext.create('Ext.data.Store',{ fields : ['reconfigure_1','reconfigure_2','reconfigure_3','reconfigure_4'], data : [{ reconfigure_1 : '재설정_데이터1', reconfigure_2 : '재설정_데이터2', reconfigure_3 : '재설정_데이터3', reconfigure_4 : '재설정_데이터4' }], proxy : { type : 'memory' } }); var reconfigure_model = [{ text : '컬럼재설정1', flex : 1, dataIndex : 'reconfigure_1' },{ text : '컬럼재설정2', flex : 1, dataIndex : 'reconfigure_2' },{ text : '컬럼재설정3', flex : 1, dataIndex : 'reconfigure_3' },{ text : '컬럼재설정4', flex : 1, dataIndex : 'reconfigure_4' }];
위와같이 각각의 데이터들을 변수에 담은 후
그리드 패널에 대한 정의를 해보도록 하겠습니다.
Ext.create("Ext.grid.Panel",{ renderTo : Ext.getBody(), title : '그리드 컬럼재설정 샘플', width : 600, height : 300, id : 'grid_object', columns :original_model, store : original_store, fbar : [{ xtype : 'button', text : '원복하기', id : 'original', disabled : true, handler : function(btn){ Ext.MessageBox.show({ title: '메시지', msg: '그리드 컬럼을 원복 하시겠습니까?', //메시지창 애니메이션 show animateTarget : btn, buttons: Ext.MessageBox.OKCANCEL, icon : Ext.MessageBox.INFO, fn : function(btn2){ if(btn2 == "ok") { Ext.getCmp("grid_object").reconfigure(original_store,original_model); Ext.getCmp("original").setDisabled(true); Ext.getCmp("reconfigure").setDisabled(false); } } }); } },{ xtype : 'button', text : '컬럼재설정', id : 'reconfigure', handler : function(btn){ Ext.MessageBox.show({ title: '메시지', msg: '그리드 컬럼을 재설정 하시겠습니까?', //메시지창 애니메이션 show animateTarget : btn, buttons: Ext.MessageBox.OKCANCEL, icon : Ext.MessageBox.INFO, fn : function(btn2){ if(btn2 == "ok") { Ext.getCmp("grid_object").reconfigure(reconfigure_store,reconfigure_model); Ext.getCmp("original").setDisabled(false); Ext.getCmp("reconfigure").setDisabled(true); } } }); } }] })
이번에는 코드가 약간 길어졌습니다.
이전 강좌를 꾸준히 구독하신 분들이시라면 보던 코드일 것입니다.
※ 데이터스토어 및 모델들을 담은 변수와 그리드패널 생성코드를
Ext.onReady 내에 정의해주세요.
간단히 그리드패널 생성부분에 대하여 설명을 드리자면
그리드패널 하단에 툴바적용 후,
버튼컴포넌트를 2개(원복하기,컬럼재설정) 생성하였습니다.
그리고 각 버튼의 handler 속성을 이용하여
클릭 이벤트 발생시 기능들을 정의해주었습니다.
클릭이벤트 발생시 다이얼로그창을 띄워서 'OK' 버튼을 클릭하게 된다면
reconfigure 함수를 적용하여 그리드 컬럼및 데이터 재 설정 후,
클릭이벤트가 발생된 버튼을 비활성시키고
다른 버튼을 활성화 시키는 함수를 적용하였습니다.
여기서 Ext.getCmp("XXX")라고 작성을 하였는데
무엇이냐면 jQuery의 아이디셀렉터와 동일한 개념의 셀렉터입니다.
Ext.getCmp("id") = $("#id")
위와같은 개념이라 생각하시면 되겠습니다.
그럼 이제 실행을 한번 하여 결과를 확인해보도록 할까요??
정상적으로 컬럼 및 데이터들의 변경이 완료되었습니다.
그리드에 대한 포스팅인 이번장으로 마무리 하도록 하겠습니다.
다음 포스팅은 트리패널에 대하여 알아보도록 하겠습니다.
by 개발로짜
ExtJS 강좌 - 마우스우클릭으로 contextmenu(컨텍스트메뉴) 띄워보기 (0) | 2014.11.08 |
---|---|
ExtJS 트리패널을 사용하여 컴포넌트 출력해보기 (memory/ajax 방식 포함) (0) | 2014.11.07 |
ExtJS 강좌 - 그리드패널에 페이징툴바를 적용하여 페이징 목록 출력하기 (10) | 2014.11.03 |
ExtJS 강좌 - 그리드패널을 출력시키기 위하여 이해를 한 후 출력시켜보자 (0) | 2014.11.03 |
ExtJS 강좌 - 데이터스토어(store)의 proxy ajax를 통하여 콤보박스 목록 출력시켜보기 (0) | 2014.10.30 |
이전 포스팅에 그리드 리스트 출력에 관하여 알아보았습니다.
간단하게 2~3개정도의 데이터만을 가지고 예를들어 별도의 페이징 처리를 하지 않았습니다.
만약 데이터가 100개,1000개,3000개등.. 데이터갯수가 많을 경우에는??? 페이징처리를 해야겠죠?
그래서 이번 포스팅은 그리드패널에 페이징툴바를 적용하여
페이징기능을 구현해보도록 하겠습니다.
DB연동은 하지않고 진행하겠습니다.
※ 실질적으로 DB연동해서 페이징 처리 및 CRUD 기능들에 대해서는 MVC 포스팅시간에 다루도록 하겠습니다!!
임의로 DB(?)데이터가 10개가 등록되어있다고 가정을 하겠습니다.
이전 포스팅에서 ajax콜을하여 작성한 샘플코드를 변경해보도록 하겠습니다.
2014/11/03 - [웹개발강좌/ExtJS] - ExtJS 강좌 - 그리드패널을 출력시키기 위하여 이해를 한 후 출력시켜보자
Ext.onReady(function(){ var store = Ext.create("Ext.data.Store",{ autoLoad : true, //기존코드에 추가된 부분 pageSize: 2, fields : ['blogger_id','blogger_name','blogger_url'], proxy : { type : 'ajax', api : { read : '/grid_res_paging.jsp' }, reader : { type : 'json', //정의하지 않을경우 default 'success'라는 값 set successProperty : "success_flag", rootProperty : 'grid_item', //정의하지 않으면 default로 'total'이라는 값 set totalProperty : 'total_count' } } }); Ext.create("Ext.grid.Panel",{ renderTo : Ext.getBody(), title : '그리드 ajax페이징 설명', width : 600, height : 300, columns : [{ text : '블로거아이디', flex : 1, dataIndex : 'blogger_id' },{ text : '블로거닉네임', flex : 1, dataIndex : 'blogger_name' },{ text : '블로그주소', flex : 1, dataIndex : 'blogger_url' }], store : store, //페이징툴바추가 dockedItems : [ { xtype : 'pagingtoolbar', //dock은 위치지정이 가능 dock : 'bottom', //gridpanel의 스토어와 동일한 데이터스토어 set store : store, displayInfo : true, displayMsg: '{0} - {1} / 총 게시물 : {2}', emptyMsg: "데이터가 없습니다" } ] }) })
위 코드를 보시면 크게 3가지의 코드가 적용되었습니다.
1. 데이터 스토어를 변수에 담다
별도로 그리드패널과 페이징툴바영역내에 store를 각각 적용해도 무관하지만
하나의 데이터 스토어를 이용하기 위하여 변수에 담아서 같은 저장공간을 사용하기위하여 정의
2. 스토어에 추가된 totalProperty 속성 및 pageSize속성
페이징 처리를 위해서 꼭 필요한 속성은 아닙니다. default로 이미 정의되어있긴 합니다.
만약 위 속성들을 정의하지않는다면 default 값들은
totalProperty : 'total'
pageSize : 25
이 되겠습니다.
둘다 정의하지 않아도 되겠지만 임의로 10개의 데이터로 페이징처리를 하는것을 보여주기위하여 pageSize속성을 2개로 잡아보았습니다.
3. dockeditems 속성을 정의
페이징툴바 컴포넌트를 적용하기 위한 속성값입니다.
displayMsg에 정의한 0/1/2에 대한 치환자의 해석은
{0} - 현재 출력된 데이터의 시작값
{1} - 현재 출력된 데이터의 마지막값
{2} - 데이터의 총 갯수
그리고 emptyMsg 속성은 데이터의 총갯수가 0일경우 나타내기 위한 메시지속성입니다.
이제 그리드컴포넌트의 목록출력을 위하여 코드에서 정의한
서버페이지(grid_res_paging.jsp)에 다음과 같은 코드를 작성해보겠습니다.
JSONArray jsonArray = new JSONArray(); JSONObject jsonGridRootObject = new JSONObject(); JSONObject jsonGridObject = null; //데이터스토어의 pageSize 속성에 정의된 숫자값(한페이지에 몇개의 데이터를 출력할것인지) String limit = request.getParameter("limit"); // start에 들어가는 값은 // 1page : 0 * limit // 2page : 1 * limit // 3page : 2 * limit // 위처럼 1,2,3 증가하는 숫자값이 아니고 0,1,2로 증가되는 인덱스값의 계산을 합니다. String start = request.getParameter("start"); int pageNum = (Integer.parseInt(start) / Integer.parseInt(limit)); //1페이지일경우 if(pageNum == 0) { jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "1page-guklife"); jsonGridObject.put("blogger_name", "1page-국이"); jsonGridObject.put("blogger_url", "1page-guklife.tistory.com"); jsonArray.add(jsonGridObject); jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "1page-hellogk"); jsonGridObject.put("blogger_name", "1page-개발로짜"); jsonGridObject.put("blogger_url", "1page-hellogk.tistory.com"); jsonArray.add(jsonGridObject); //2페이지일 경우 } else if(pageNum == 1) { jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "2page-guklife"); jsonGridObject.put("blogger_name", "2page-국이"); jsonGridObject.put("blogger_url", "2page-guklife.tistory.com"); jsonArray.add(jsonGridObject); jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "2page-hellogk"); jsonGridObject.put("blogger_name", "2page-개발로짜"); jsonGridObject.put("blogger_url", "2page-hellogk.tistory.com"); jsonArray.add(jsonGridObject); //3페이지일경우 } else if(pageNum == 2) { jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "3page-guklife"); jsonGridObject.put("blogger_name", "3page-국이"); jsonGridObject.put("blogger_url", "3page-guklife.tistory.com"); jsonArray.add(jsonGridObject); jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "3page-hellogk"); jsonGridObject.put("blogger_name", "3page-개발로짜"); jsonGridObject.put("blogger_url", "3page-hellogk.tistory.com"); jsonArray.add(jsonGridObject); //4페이지일경우 } else if(pageNum == 3) { jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "4page-guklife"); jsonGridObject.put("blogger_name", "4page-국이"); jsonGridObject.put("blogger_url", "4page-guklife.tistory.com"); jsonArray.add(jsonGridObject); jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "4page-hellogk"); jsonGridObject.put("blogger_name", "4page-개발로짜"); jsonGridObject.put("blogger_url", "4page-hellogk.tistory.com"); jsonArray.add(jsonGridObject); //5페이지일 경우 } else if(pageNum == 4) { jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "5page-guklife"); jsonGridObject.put("blogger_name", "5page-국이"); jsonGridObject.put("blogger_url", "5page-guklife.tistory.com"); jsonArray.add(jsonGridObject); jsonGridObject = new JSONObject(); jsonGridObject.put("blogger_id", "5page-hellogk"); jsonGridObject.put("blogger_name", "5page-개발로짜"); jsonGridObject.put("blogger_url", "5page-hellogk.tistory.com"); jsonArray.add(jsonGridObject); } jsonGridRootObject.put("success_flag", true); jsonGridRootObject.put("grid_item", jsonArray); //데이터 목록의 총 데이터수를 넘겨주어야 한다 jsonGridRootObject.put("total_count", 10); response.setContentType("text/plain; charset=UTF-8"); PrintWriter pw = response.getWriter(); pw.print(jsonGridRootObject); pw.flush(); pw.close();
위 코드를 보시면 이전 ajax 샘플코드에 추가로
분기로 임의의 데이터를 json object를 만들어서 response해주게끔 변경을 하였습니다.
한번 실행을 해보겠습니다.
1페이지
2페이지
3페이지
4페이지
5페이지
실행결과 페이징기능이 정상적으로 구현된 것을 확인 할수 있었습니다.
등록/수정/삭제 및 DB를 이용한 조회 기능은 초반에 말씀드렸다시피
MVC구조에 대한 개념을 익힌 후에
웹어플리케이션 샘플예제를 진행할때 다루도록 하겠습니다.
by 개발로짜
ExtJS 트리패널을 사용하여 컴포넌트 출력해보기 (memory/ajax 방식 포함) (0) | 2014.11.07 |
---|---|
ExtJS의 그리드패널 reconfigure함수를 적용하여 컬럼 및 데이터 재설정하기 (0) | 2014.11.05 |
ExtJS 강좌 - 그리드패널을 출력시키기 위하여 이해를 한 후 출력시켜보자 (0) | 2014.11.03 |
ExtJS 강좌 - 데이터스토어(store)의 proxy ajax를 통하여 콤보박스 목록 출력시켜보기 (0) | 2014.10.30 |
ExtJS 강좌 - 콤보박스를 예를들어 스토어(STORE) 개념잡아보기 (0) | 2014.10.30 |