자바스크립트이야기/ExtJS

[ExtJS강좌 25] MVC 그리드(GridPanel) 를 이용한 CRUD예제

개발로짜 2014. 7. 16. 21:07

오랫만에 ExtJS 강의를 올리게 되었다.. 슬퍼2슬퍼2


마땅히 프로젝트 주제를 정하고 정하다가 결국은 심플하게 하기로 정하였다;;;


이번 다룰 주제는 ExtJS MVC 기반을 이용하여 간단? 회원관리 테이블을 만들어볼 예정이다.


해당 주제에서 핵심은 GRID를 통하여 DB에 대한 CRUD 기능을 모두 적용하는 것임.


전에는 GRID에 대하여 LIST 출력하는 내용만 기술하였는데 이번 프로젝트를 통해서 


CRUD를 모두 적용해보도록 하겠음. 셀카


컴포넌트 설정 및 내용에 대하여는 이전 포스팅에 여러가지 올려놨으니 순서대로 차근차근 

보시는걸 추천드림.


우선적으로 웹소스 + DB 커넥션에 대한 설정은 제외 하도록 하겠음.


자 그럼 그리드를 이용한 CRUD 설명 GO!


1. 자신이 작업하려는 환경의 DB에 다음과 같은 테이블 생성!!  (MYSQL 기준) 

CREATE TABLE member(  
  seq INT NOT NULL AUTO_INCREMENT COMMENT '회원번호',
  member_name VARCHAR(20) NOT NULL COMMENT '회원이름',
  member_birth VARCHAR(8) NOT NULL COMMENT '회원생년월일',
  member_mobile VARCHAR(11) NOT NULL COMMENT '회원연락처',
  create_date DATETIME NOT NULL COMMENT '등록일',
  PRIMARY KEY (`seq`)
) ENGINE=INNODB CHARSET=utf8;

2. 지난 시간에 설정한 MVC 구조기준으로 controller/model/store/view를 새로구성

   하기 위해 파일들을 새로 생성해보았다.


    


화면의 mvc.js에서 변경된 것이 있다고 한다면  기존에는  controllers의 값을 

'MVCController'  -> 'MemberController' 이걸로 변경한것이 전부다.

name 명칭을 바꿔주면 cotroller/model/store/view에 대한 모든 define 명칭을 변경해주는것이 

귀찮아서 mvc로 냅둔상태...


자~ TABLE 도 생성했으니 1차적으로 MemberModel.js를 먼저 정의해두도록 하자

흐름방식을 model -> store -> view -> viewport -> controller 로 진행하는것이 수월할듯함... 


1. model 관련

   그냥 단순하게 crud 를 확인하고자 하는것이니 fields의 명칭은 테이블의 명칭과 

   맞추어 주었다.


Ext.define('mvc.model.MemberModel', {
    extend: 'Ext.data.Model',
    fields: [
	    {name: 'seq', type: 'int'},
	    {name: 'member_name', type: 'string'},
	    {name: 'member_birth', type: 'string'},
	    {name: 'member_mobile', type: 'string'},
	    {name: 'create_date', type: 'date'}
	    /*{name: 'create_date', type: 'string'}*/
    ]
});


2. store 관련

   Model을 사용할 Store부분을 보도록 하자 


Ext.define('mvc.store.MemberStore', {
    extend: 'Ext.data.Store',
    model: 'mvc.model.MemberModel',
    autoLoad: true, 
    proxy: {
        type: 'ajax',
        api: {
        	// insert page
        	create : '/create',
        	// select page
        	read: '/list',
        	// update page
        	update : '/update',
        	// delete page
        	destroy : '/delete'
        },
        //select option
        reader: {
            type: 'json', 
            successProperty: 'success',
            rootProperty: 'items'
        },
        //create,update,delete option
       writer: {
	        type: 'json',
	        //그리드 row의 모든값 전송
	        writeAllFields: true,
	        //필수속성값
	        encode : true,
	        //server (request param id)
	        rootProperty: 'data'
	    }
    }
});


뭔가 드~~럽게 많이 추가되었다. 흥5

예전 grid 페이징을 했을경우, proxy -> api가 read랑 proxy의 reader 속성만 다루었었는데

추가로 api의 속성들이 create / read / destroy 이 세개가 추가되었고 writer 라는 속성이 추가 

되었다.

이와같이 추가된 속성들은 insert / update / delete  db 처리 작업을 하기위하여 필요한 놈들이다 +_+ ㅋㅋㅋ



3. view 관련 

   gridpanel 을 view에 정의해주도록 하자 


Ext.define('mvc.view.MemberGrid', {
    extend: 'Ext.grid.Panel',
    alias : 'widget.memberGrid',
    store : 'MemberStore',
    columns: [
   			  { 
				dataIndex : 'seq',
				text : '회원번호'			
			},
			{
				dataIndex : 'member_name',
				text : '회원이름',
				editor : 'textfield'
			},
			{
				dataIndex : 'member_birth',
				text : '생년월일',
				editor : 'textfield'					
			},
			{
				dataIndex : 'member_mobile',
				text : '연락처',
				editor : 'textfield'				
			},
			{
				dataIndex : 'create_date',
				text : '등록일',
				flex : 1
			}
    ],
    //그리드 컬럼을 수정하기위하여 필요한 ExtJS 관련 플러그인 {clicksToEdit: 1} << 제거후
    //수정하려면 컬럼 더블클릭해야함 해당옵션은 한번클릭으로 그리드 컬럼 수정가능
    plugins: [new Ext.grid.plugin.CellEditing({clicksToEdit: 1})],
    tbar : [
	    {
	    	//추가버튼
	    	xtype :'button',
	    	text : '추가',
	    	id : 'addBtn'
	    	
	    },
	    {
	    	//삭제버튼
	    	xtype :'button',
	    	text : '삭제',
	    	id : 'removeBtn'
	    	
	    },
	    {
	    	//적용버튼
	    	xtype :'button',
	    	text : '적용',
	    	id : 'syncBtn'
			
	    }
    ],
    initComponent: function() {
        this.callParent();
    }
});

4.컨트롤러 관련


Ext.define('mvc.controller.MemberController', {
    //기본상속
    extend: 'Ext.app.Controller',
    refs: [
       {
	        ref: 'memberGrid',
	        selector: 'memberGrid'
       }
	],
	stores : ['MemberStore'],
    views: ['MemberGrid'],
    init: function() {
        this.control({
        	//멤버그리드 컴포넌트내에 존재하는 버튼셀렉터
        	'memberGrid button' : {
        		//클릭이벤트 발생시 controller에 존재하는
        		//gridHandleButton 함수를 호출
        		click : this.gridHandleButton
        	}
        });
    },
    gridHandleButton : function(btn) {
    	//그리드 객체
    	var grid = this.getMemberGrid();
    	//그리드 -> 저장공간 객체
    	var gridStore = grid.getStore();
    	//그리드 행 추가버튼 클릭
    	if(btn.getId() == "addBtn") {
    		//membermodel
    		var rec = new mvc.model.MemberModel({
                seq: '',
                member_name : '',
                member_birth: '',
                member_mobile: '',
            	create_date: ''
            });
    		//store에 로우 추가
            gridStore.insert(0, rec);
            //에디트 시작포커스 잡기 (없으면 단순 로우만 추가)
            grid.plugins[0].startEditByPosition({
                row: 0,
                column: 1
            });
    	} else if(btn.getId() == "removeBtn") {
    		//그리드 로우 삭제
    		grid.getStore().remove(grid.getSelectionModel().getSelection());
    	} else if(btn.getId() == "syncBtn") {
    		//create,update,destroy 처리를 한다
    		grid.getStore().sync({
    			callback : function(){
    				//insert/update/delete 후에 리스트 재호출
    	    		grid.getStore().reload();		
    			}
    		});
    	}
    }
}); 


현 예제에서는 오류 관련은 다루지 않는다.

sync 일 경우 store에서 정의했던 create/update/destroy 속성을 각각호출한다.

한꺼번에 호출할수도 있는데 조금 복잡하므로 추후 시간이 나면 다루도록 하겠음

crud의 핵심은 store에 정의된 proxy url영역이고 컨트롤러의 store load/sync 함수이다!

list는 화면에 출력해주는 것이므로 reader -> rootProperty의 items가 response 해주는 

json root 객체인 셈이다.

db 호출후 서버에서 클라이언트로 응답해주는 json 객체의 json 문자열은 다음과 같다.

파싱관련은 본인이 사용하는 json object 생성 라이브러리를 이용하여 파싱해주도록 하자


// read url 호출시 list json객체
{
"items":
	[
		{"seq":"9","member_name":"333","member_birth":"333","member_mobile":"333","create_date":"2014-07-1623:20:35.0"},
		{"seq":"7","member_name":"11","member_birth":"11","member_mobile":"11","create_date":"2014-07-1623:20:22.0"}
	]
}


거꾸로 create/update/destroy에서 정해준 writer 속성의 rootProperty로 정해준 키값으로 서버

에서 데이터를 request 하게되면json 문자열로 파라미터를 받을수 있다.

writer의 rootProperty 값을 data 정의해준거면 서버에서 request.getParameter("data") 로 

받으면 다음처럼 데이터를 받을 수 있다.


//seq는 자동증가값이므로 입력할 필요없다 
// create_date 역시 null인대 쿼리문 자체에서 now()로 주므로 의미가 없다.
[
	{"seq":0,"member_name":"222","member_birth":"444","member_mobile":"555","create_date":null,"id":"mvc.model.MemberModel-4"},
	{"seq":0,"member_name":"111","member_birth":"333","member_mobile":"444","create_date":null,"id":"mvc.model.MemberModel-3"}
]


writer의 json 속성중 id 는 별의미 없다.

마지막으로 서버에서 가공해줘야 하는 순서는 다음과 같다.


1. 문자열 json을 json object 또는 json array 로 변경해주어야함 


2. json array 및 json object에 대하여 쿼리를 가공하여 db처리를 해준다.

   해당 샘플은 본인이 테스트로 만든 서버 로직이다. 

   (json-simple library 를 이용하였다)


////////////////////// "/create 호출 페이지" /////////////////////////

//object일수도 있고 array일수도 있다. object 변환후 json array에 담는다.
                JSONObject jsonObj = null;
		JSONObject jsonObject = null;
		JSONArray jsonArr = null;
		String data = request.getParameter("data");
		if(data.substring(0,1).equals("{")) {
			jsonObject = JSONObject.fromObject(JSONSerializer.toJSON(data));
			jsonArr = new JSONArray();
			jsonArr.add(jsonObject);
		} else if(data.substring(0,1).equals("[")) {
			jsonArr = JSONArray.fromObject(data);	
		}
		
		if(jsonArr.size() > 0){
			for(int i=0; i<jsonArr.size(); i++) {
				jsonObj = (JSONObject)jsonArr.get(i);
				String query = "";
				query += " INSERT INTO member(member_name,member_birth,member_mobile,create_date) ";
				query += " VALUES('"+jsonObj.get("member_name")+"','"+jsonObj.get("member_birth")+"','"+jsonObj.get("member_mobile")+"',now()) ";
				service.executeQuery(query);
			}
		}
		jsonObj = new JSONObject();
		jsonObj.put("success", true);
                PrintWriter pw = response.getWriter();
		pw.print(jsonObj);
		pw.flush();
		pw.close();


위와 같이 작업한결과 이상없이 동작하는것을 확인하였다.

영상으로 동작과정을 보고 마무리를 하도록 하겠음!!







슈퍼맨슈퍼맨슈퍼맨



도움이 되셨다면 공감클릭! 궁금하신점은 댓글!!