지난 시간에 이어서 트리패널에 대해서 조금 더 알아보는 시간을 가져보도록 하겠습니다.

    이번강좌는 Ajax 통신을하여 트리의 하위노드들을 Load 해보도록 하겠습니다.

    파일로 데이터를 한번에 로드하는 방식DB내에 테이블을 생성하여 데이터 조회 후, 하위노드를 호출하는방식을 이용하여 이번 강좌를 진행해보겠습니다.

    코드는 이전 포스팅에서 작성했던 코드를 이용하여 변경 작업 후, 테스트를 해보도록 하겠습니다.

    ① 트리패널 Ajax 파일호출

    클라이언트코드와 JSON 파일내에 입력 할 데이터를 작성 후, 설명을 드리도록 하겠습니다.


    ExtJS 샘플코드

    
    Ext.onReady(function(){
    	Ext.create('Ext.tree.Panel',{
    		width : 500,
    		height : 800,
    		title : 'Tree Ajax File Load Example',
    		store : Ext.create('Ext.data.TreeStore',{
    						 root : {
    							    text: '몽고소프트',
    							    expanded: false
    						 },
    						 proxy: {
    		                    type: 'ajax',
    		                    url: './tree.json',
    		                    reader: {
    		                        type: 'json',
    		                        rootProperty: 'children'
    		                    }
    		                }
    				}
    		),
    		renderTo : Ext.getBody()
    	})
    })
    
    

    JSON 데이터 (tree.json)

    
    {
    children: [
    	{ 
    		leaf:true, 
    		text: '대표-세종대왕' 
    	},{
            text: '경영지원팀',
            expanded: true,
            children: [{ 
            		leaf:true, 
            		text: '부장-홍길동' 
        		}]
        },{
            text: '기획팀',
            expanded: true,
            children: [{ 
            		leaf:true, 
            		text: '차장-이순신' 
        		},{ 
    				leaf:true, 
    				text: '과장-장영실' 
    			}]
        },{
            text: '개발팀',
            expanded: false,
            children: [{ 
            		leaf:true, 
            		text: '부장-스티브잡스' 
        		},{ 
    				leaf:true, 
    				text: '차장-빌게이츠' 
    			},{ 
    				leaf:true, 
    				text: '대리-주커버크' 
    				},{ 
    					leaf:true, 
    					text: '사원-몽고' 
    			}]
        }
    ]
    }
    
    

    실행결과


    실행결과는 이전 포스팅의 결과와 동일합니다.

    코드만 나누었을 뿐이니까요.

    대신, 최초 호출시 로딩바가 잠깐 생기는걸 확인 하실 수 있습니다.

    비동기 호출시 나타나는 화면이니 신경쓰지 않으셔도 됩니다.


    ExtJS 코드에서 root config 내에 children JSON 데이터를 제거하고, proxy config를 이용하여 Ajax Call을 통하여 tree.json 파일내에 존재하는 JSON 유형의 데이터를 로드해오는 구조로 변경하였습니다.

    질문 : tree.json 파일내에 children JSON Array 유형이 {  } 사이에 존재하던대, 이유는?

    답 : Grid JSON Reponse 방식과 동일하게 rootProperty에 정의된 JSON Data만 존재하는 것이아니고, success / total 등 몇가지 결과값이 추가로 필요하기때문입니다.

    물론 successProperty와 totalProperty 속성을 정의해주지 않아도 rootProperty에 속한 데이터만 존재해도 충분히 결과물이 나옵니다.

    올바른규격

    
    {
      success : true,
      children : [],
      total : 0 
    }
    
    

    잘못된규격

    
    children : [
    {},{}
    ]
    
    

    위와같이 올바른 JSON 규격을 기억하도록 합니다.


    ② 트리패널 Ajax DB조회 호출

    방금 다루었던 파일 호출하는 데이터를 DB로부터 조회하여 하위노드로 출력해야하므로, 동일한 구조로 테이블 생성 후, 데이터를 추가 해보도록 하겠습니다.

    첨부된 파일을 다운로드 후, 자신의 DB에 IMPORT 해주세요.



    데이터들이 테이블이 등록되었습니다. ▲


    기존 JSON 파일호출한 코드에서 다음과 같이 변경을 해줍니다. ▼

    1. TreeStore → root config 내에 id : 0 을 추가합니다.

    id가 추가된 root config 코드

    
    root : {
        text: '몽고소프트',
        expanded: false,
        //added
        id : 0
    }
    
    

    2. proxy → url값을  server3_select.jsp 로 변경


    위 작업이 완료되었다면, 서버페이지(server3_select.jsp) 파일내에 정의한 코드는 다음과 같습니다. ▼


    
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    try{
    	JSONObject jsonObject = new JSONObject();
    	JSONArray jsonArray = new JSONArray();
    	JSONObject subObject =  null;
    	
    	//Clicked idx (client Key = id)
    	String click_node = request.getParameter("node");
    	
    	/**
    	*	JDBC 정보 설정 (MySQL)
    	*/
    	String url = "jdbc:mysql://localhost:3306/test";
    	String id = "root";
    	String pwd = "autoset";                             
    	
    	Class.forName("com.mysql.jdbc.Driver");
    	conn=DriverManager.getConnection(url,id,pwd);
    	stmt = conn.createStatement();
    	
    	/**
    	*	목록조회 + 페이징
    	*/
    	String list_sql = " SELECT a.idx, a.text, (SELECT COUNT(*) "; 
    		   list_sql += "					    FROM treedata b "; 
    		   list_sql += "					   WHERE b.parent_idx = a.idx) count "; 
    		   list_sql += "  FROM treedata a ";
    		   list_sql += " WHERE a.parent_idx = " + click_node;
    	
    	rs = stmt.executeQuery(list_sql);
    	
    	while(rs.next()){
    		subObject = new JSONObject();
    		subObject.put("id", rs.getInt("idx"));
    		subObject.put("text", rs.getString("text"));
    		//child node presence
    		if(rs.getInt("count") > 0) {
    			subObject.put("expanded", false);
    		//child node does not presence
    		} else {
    			subObject.put("leaf", true);
    		}
    		jsonArray.add(subObject);
    	}
    	
    	jsonObject.put("success", true);
    	jsonObject.put("children", jsonArray);
    	
    	response.setContentType("text/plain; charset=UTF-8");
    	PrintWriter pw = response.getWriter();
    	pw.print(jsonObject);
    	pw.flush();
    	pw.close();
    }catch(Exception e){
    	e.printStackTrace();
    }
    
    


    이전 그리드 목록 조회한 코드에서 일부 변경을 하였습니다.

    트리가 확장이벤트(expanded) 발생 시, 선택된 노드의 값을 서버로 전송합니다.

    서버에서 받기위해서는 key값을 "node" 로 받아서 처리해야하며,

    JSON 파일에는 root config내에 id가 존재하지 않았으나, DB처리를 위해서는 id config 값이 필요합니다.(중요합니다. )

    이유는 설정을 해주지 않을경우, 최초클릭시 'root' , 이후 하위노드 클릭할때마다 xxxx-Model 관련 데이터가 넘어오기 때문입니다.

    즉, id config가 출력되는 노드의 고유키값이 되는겁니다.

    쿼리에는 id값과 노드에 표출될 타이틀 외에도 자식노드 존재유무를 판단하기 위한 count 컬럼을 추가하였습니다.

    이유는 최종 하위노드일 경우 leaf : true를 적용해줘야 한다고 말씀드렸었죠?

    바로 그이유 때문입니다.

    불필요한 쿼리조회를 하지 않기 위함입니다.

    물론, 다른방식이 있다면, 자신만의 방식으로 처리하셔도 무관합니다.

    그 외에는 기존 그리드 조회했던 방식처럼 rootProperty config에 적용한 value 값에 맞춰 JSON Object로 클라이언트 페이지로 응답해주면 서버페이지의 역할은 모두 다한 것입니다.

    실행을 해보도록 하겠습니다.


    실행결과



    클릭 할때마다 로딩바다 잠시 나타나면서 DB에 저장되어있는 데이터들을 정상적으로 출력합니다.




    Posted by 몽고