오랫만에 jQuery 포스팅을 하게 되었습니다.
오늘 작성해볼 포스팅은 jQuery 이벤트들에 대하여 알아볼까 하는대요.
그중 몇가지만 설명과 예를들어 포스팅 해보도록 하겠습니다.
모든 이벤트의 테스트를 간단하게 적용하기 위하여 이벤트 발생시 alert 을 화면에 출력시켜보도록 하겠습니다.
보통 button 및 a태그에 자주 적용되는 이벤트인대요.
꼭 버튼이나 a태그 말고도 그외의 태그에도 적용이 가능합니다.
한번 버튼 태그에 클릭이벤트를 적용해보는 코드를 작성해보겠습니다.
jQuery CDN을 이용하여 예를 드는 것이니 별도로 jQuery 버전에 대해서는 본인이 사용중인 버전을 이용하셔도 무관합니다.
2014/10/08 - [웹개발강좌/jQuery] - jQuery 1강 - jQuery 연동부터 $(document).ready() 이해하기
<input type="button" id="btn" value="클릭"/>
$(function(){ $("#btn").click(function(){ //클릭이벤트 발생시 진행할 스크립트 작성 alert("클릭입니다!!"); }) })
클릭이벤트는 특정 타겟에 클릭이 한번 이루어졌을 경우 발생되는 이벤트일때 사용이 됩니다.
더 나아가 특정 태그에 연속으로 두번클릭이 이루어졌을 경우 더블클릭 이벤트를 실행시킵니다.
자주 사용되지는 않지만 알아보도록 해보겠습니다.
<input type="button" id="dblbtn" value="더블클릭"/>
$(function(){ $("#dblbtn").dblclick(function(){ //더블클릭이벤트 발생시 진행할 스크립트 작성 alert("더블클릭입니다!!"); }) })
change이벤트는 보통 select 박스의 값이 변경되었을 경우 발생되는 이벤트입니다.
한번 selectbox 를 변경해보면서 선택값을 출력해보는 예제코드를 작성해봅니다.
<select id="slct"> <option value="1">첫번째</option> <option value="2">두번째</option> </select>
$("#slct").change(function(){ //셀렉트박스 발생시 진행할 스크립트 작성 //선택된 값을 alert으로 출력해보는 샘플코드 var selectvalue = $("#slct").val(); alert("변경이되었습니다.(선택된값은:"+selectvalue+")입니다."); })
일반적으로 input 박스에서 키보드의 키가 눌리는 현상이 나타날때 발생되는 이벤트입니다.
상황에 따라 사용을 해주셔야 할거 같습니다.
※ keypress 및 keydown은 키보드가 눌리는 즉시 발생되므로 console.log가 지원이 되는 브라우저 환경에서 진행 하시기를 권유합니다.
만약 console.log 이벤트가 지원되지 않는 브라우저진행 시 alert으로 변경해서 테스트 하시길 바랍니다.
<input type="text" id="key2"/>
$("#key2").keypress(function(){ //input 키보드 눌리는 이벤트 발생시 진행할 스크립트 작성 console.log("키보드누름 이벤트 발생중..."); })
일반적으로 input 박스에서 키보드의 키가 눌렀다가 떼었을때 발생되는 이벤트입니다.
<input type="text" id="key"/>
$("#key").keyup(function(){ //input 키보드 눌렀다 떼어지는 이벤트 발생시 진행할 스크립트 작성 alert("눌렀다가 떼었다"); })
마우스 이벤트의 한 종류로 토글과 비슷한 기능을 가지는 이벤트입니다.
마우스 포인터가 특정 타겟에 위치했을 경우/ 벗어났을 경우에 대한 이벤트를 가집니다.
다음예제는 div 태그에 마우스포인터를 가져갔을 경우 특정 class를 적용하여 div 레이어의 배경색이 파란색으로 변경되며
글자색은 흰색으로 변경되는 class를 적용하고 벗어날경우 해당 class를 제외하는 기능입니다.
<div id="mousehover"> 마우스를 올리면 영역의 색깔이 변합니다. </div>
$("#mousehover").hover( //타겟에 마우스포커스가 잡혔을 경우 function(){ //div class 속성에 hover_class라는 클래스를 추가 $("#mousehover").attr("class","hover_class"); } //타겟에 마우스포커스가 벗어났을 경우 ,function(){ //div class 속성에 hover_class라는 클래스를 제거 $("#mousehover").attr("class",""); }) })
.hover_class { background-color: blue; color: white; }
포커스 이벤트는 특정 태그에 초점을 주기위한 이벤트로 주로 validation 체크시 종종 사용되는 이벤트입니다.
다음 코드를 보시면 쉽게 이해가 되실겁니다.
<input type="text" id="focusTxt" /> <input type="button" id="focusBtn" value="text포커스이동" />
$("#focusBtn").click(function(){ $("#focusTxt").focus(); }) })
지금까지 주로 사용하는 이벤트들에 대해서 작성해보았습니다.
조금 더 상세하고 많은 이벤트가 궁금하시면 하단 Document URL 을 이동하여 확인 해주시기 바랍니다.
http://api.jquery.com/category/events/
지금까지 작성한 코드를 일괄로 작성한 코드는 다음과 같습니다.
<input type="button" id="btn" value="클릭"/> <br/> <input type="button" id="dblbtn" value="더블클릭"/> <br/> <select id="slct"> <option value="1">첫번째</option> <option value="2">두번째</option> </select> <br/> <input type="text" id="key"/> <br/> <input type="text" id="key2"/> <br/> <div id="mousehover"> 마우스를 올리면 영역의 색깔이 변합니다. </div> <br/> <input type="text" id="focusTxt" /> <input type="button" id="focusBtn" value="text포커스이동" />
$(function(){ $("#btn").click(function(){ //클릭이벤트 발생시 진행할 스크립트 작성 alert("클릭입니다!!"); }) $("#dblbtn").dblclick(function(){ //더블클릭이벤트 발생시 진행할 스크립트 작성 alert("더블클릭입니다!!"); }) $("#slct").change(function(){ //셀렉트박스 발생시 진행할 스크립트 작성 //선택된 값을 alert으로 출력해보는 샘플코드 var selectvalue = $("#slct").val(); alert("변경이되었습니다.(선택된값은:"+selectvalue+")입니다."); }) $("#key2").keypress(function(){ //input 키보드 눌리는 이벤트 발생시 진행할 스크립트 작성 console.log("키보드누름 이벤트 발생중..."); }) $("#key").keyup(function(){ //input 키보드 눌렀다 떼어지는 이벤트 발생시 진행할 스크립트 작성 alert("눌렀다가 떼었다"); }) $("#mousehover").hover( //타겟에 마우스포커스가 잡혔을 경우 function(){ $("#mousehover").attr("class","hover_class"); } //타겟에 마우스포커스가 벗어났을 경우 ,function(){ $("#mousehover").attr("class",""); }) $("#focusBtn").click(function(){ $("#focusTxt").focus(); }) })
.hover_class { background-color: blue; color: white; }
지금까지 자주 사용되는 jQuery 이벤트에 대하여 알아보았습니다.
다음장은 레이어를 화면에 보여주고 숨겨주는 몇가지 기능에 대하여 알아보도록 하겠습니다.
by 개발로짜
jQuery 7강 - 공백제거(trim) 및 반복문(each)에 대하여 간단하게 알아보자 (2) | 2014.12.02 |
---|---|
jQuery 6강 - (Traversing) 특정 태그로부터 다른 태그의 위치 찾아보기 (2) | 2014.12.01 |
jQuery 5강 - input태그,태그속성을 이용하여 셀렉터 알아보기 (1) | 2014.11.27 |
jQuery 4강 - attr() vs prop() 함수의 차이점을 비교하여 알아보자 (4) | 2014.11.15 |
jQuery 3강 - html() vs text() 함수 차이점 알아보기 + val() 함수를 이용한 input 태그의 값 확인 추가 (0) | 2014.11.12 |
이번에는 지난 포스팅에 이어서 그리드 페이징 처리 및
버튼 handler를 click 리스너 이벤트로 변경을 하여
컨트롤러에 담아보도록 해보겠습니다.
이전 강의에 이어서 진행하게 되므로
이전 포스팅을 우선 진행 하신다음
이어서 해당 포스팅을 참조하시면 되겠습니다.
2014/12/29 - [웹개발강좌/ExtJS] - ExtJS 강좌 - ExtJS5 MVC 구조를 이용한 간단 그리드 CRUD 알아보기(1)
그럼 기존 코드에서 약간 코드들을 수정해보면서 하단처럼 그리드 페이징처리와
버튼 클릭을 handler 가 아닌 컨트롤러에 클릭이벤트로 적용을 해보도로 하겠습니다.
Ext.define('mvc_study.view.grid.CustomGrid', { extend: 'Ext.grid.Panel', //xtype에 들어가는 컴포넌트 명칭이다. //widget. << 이부분을 제외한 나머지명칭을 xtype에 선언 해주면 됨 alias : 'widget.customGrid', title : '그리드 CRUD', //로우에디터를 사용하기 위한 플러그인 설정 plugins: [Ext.create('Ext.grid.plugin.RowEditing', { clicksToMoveEditor: 1, autoCancel: false })], columns : [ //idx 컬럼은 수정이불가하므로 editor 속성을 제거 //그외 title,name에만 editor 속성 허용 { text : '번호', flex : 1, dataIndex : 'idx' },{ text : '제목', flex : 1, dataIndex : 'title', editor: { xtype: 'textfield' } },{ text : '이름', flex : 1, dataIndex : 'name', editor: { xtype: 'textfield' } }], store : 'GridStore', dockedItems : [ { //페이징 툴바 xtype : 'pagingtoolbar', //그리드로부터 툴바생성위치 dock : 'bottom', //store store : 'GridStore', //정보 보여주기 false일 경우 하단속성은 필요없음 displayInfo : true, //보여주기 메시지(데이터 존재할때) displayMsg: '현재데이터 : {0} - {1} / 총데이터 : {2}', //데이터 존재하지 않을경우 emptyMsg: "데이터없음" } ], fbar : [{ xtype : 'button', text : '추가', id : 'addBtn' },{ xtype : 'button', text : '삭제', id : 'removeBtn' },{ xtype : 'button', text : '적용', id : 'applyBtn' }], initComponent: function() { this.callParent(); } });
위에 코드에 설명을 추가하자면 페이징 처리를 위하여
"pagingtoolbar" 컴포넌트를 dockedItems 속성내에 정의를 하였습니다.
MVC를 사용안하고 페이징 툴바에 관한 포스팅은 하단을 참고해주세요
2014/11/03 - [웹개발강좌/ExtJS] - ExtJS 강좌 - 그리드패널에 페이징툴바를 적용하여 페이징 목록 출력하기
autoLoad : true, 코드 다음에 하단 코드를 추가해줍니다.
pageSize: 3,
pageSize속성은 한페이지당 출력할 데이터 갯수를 의미합니다.
이어서 GridStore의 reader 자식 속성에 다음 코드를 추가합니다.
,totalProperty: 'totalCount'
reader의 자식속성에 존재하는 rootProperty와 동일하게
totalProperty에 정의된 속성값 역시 서버 페이지에서 응답받는 json의 key값과 동일하게 맞춰줍니다.
※ totalProperty는 원격서버로부터 페이징시 필요한 속성값이므로 기억해두도록 합니다.
★★★★★★
Ext.define('mvc_study.controller.MvcController', { extend: 'Ext.app.Controller', stores : ['GridStore'], views: ['grid.CustomGrid'], init: function() { this.control({ '#addBtn' : { click : this.addBtn }, '#removeBtn' : { click : this.removeBtn }, '#applyBtn' : { click : this.applyBtn } }); }, addBtn : function(btn){ //GridModel var rec = Ext.create('mvc_study.model.GridModel',{ title: '', name : '' }); //로우 추가 btn.up("grid").getStore().insert(0,rec); //에디트 포커스 btn.up("grid").plugins[0].startEdit(0, 0); }, removeBtn : function(btn){ //선택된 로우 삭제 btn.up("grid").getStore().remove(btn.up("grid").getSelectionModel().getSelection()); }, applyBtn : function(btn){ //각 row 마다 싱크를 맞춰주면서 btn.up("grid").getStore().sync({ //성공시 success: function( response ) { //그리드 select btn.up("grid").getStore().load(); } }); } });
MvcController에서 변경 및 추가된 점이 있다면
init의 this.controller부분에 CustomGrid에 선언한
버튼아이디셀렉터 : {
리스너이벤트명칭1(ex:click) : 함수명
리스터이벤트명칭2(ex:render) : 함수명
}
위처럼 선언이 되어있는데 이 구조 또한 기억해두도록 합니다.
그리고 함수명을 선언한 명칭으로 컨트롤러 영역에 선언한
함수명 : function(){
// 기능정의
}
처럼 지정을 해놓았습니다.
기능정의 부분은 이전에 선언한 CustomGrid 커스텀 컴포넌트의
버튼 handler 영역의 코드를 그대로 가져다 사용하였습니다.
간단하게 설명을 드려보자면
id가 "addBtn" 인 컴포넌트의 클릭이벤트 발생시 addBtn 함수 호출
id가 "removeBtn" 인 컴포넌트의 클릭이벤트 발생시 removeBtn 함수 호출
id가 "applyBtn" 인 컴포넌트의 클릭이벤트 발생시 applyBtn 함수 호출
형태로 동작이 되는 것입니다.
스크립트 코드수정이 이로써 마무으리!!가 되었습니다.
이어서 서버페이지 부분에 대한 코드를 재작성 해보도록 하겠습니다.
@RequestMapping("/listData") public @ResponseBody Map<String , Object> listData(HttpServletRequest request) throws SQLException { Map<String, Object> parameterMap = new HashMap<String, Object>(); Map<String, Object> resultMap = new HashMap<String, Object>(); //게시물 목록 수 조회 int totalCount = dao.totalCount(); //----클라이언트 페이지로부터 넘어온 parameter값들---- int start = Integer.parseInt(request.getParameter("start")); int end = Integer.parseInt(request.getParameter("limit")); //----클라이언트 페이지로부터 넘어온 parameter값들---- parameterMap.put("start", start); parameterMap.put("end", end); //게시물 목록 조회 ArrayList<Map<String, Object>> list = dao.listData(parameterMap); resultMap.put("success", true); resultMap.put("items", list); //그리드 페이징을 위한 필수 response json key 값 resultMap.put("totalCount", totalCount); return resultMap; }
DB호출하는 쿼리 페이지는 다음과 같이 변경 및 추가하였습니다.
<select id="totalCount" resultType="Integer"> SELECT COUNT(*) FROM grid </select> <select id="listData" parameterType="java.util.Map" resultType="java.util.Map"> SELECT idx,title, name FROM grid ORDER BY idx DESC LIMIT #{start}, #{end} </select>
INSERT/UPDATE/DELETE 로직은 변경사항이 없으므로 기능은 정의하지 않았습니다.
그럼 실행결과를 보도록 해보겠습니다.
정상적으로 컨트롤러 영역에 리스너 이벤트가 정상적으로 동작되는 것을 확인 하였습니다.
또한 그리드 페이징 처리 역시 잘 나오네요 ^^
by 개발로짜
ExtJS 강좌 - ExtJS5 MVC 구조를 이용한 간단 그리드 CRUD 알아보기(1) (13) | 2014.12.29 |
---|---|
Spring @ResposeBody를 이용하여 JSON Response 할때 IE에서 다운로드현상 해결법 (4) | 2014.12.07 |
ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View/Controller + Model+Store 추가) (0) | 2014.11.26 |
ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View+Controller 연동) (2) | 2014.11.26 |
ExtJS 강좌 - Sencha CMD로 ExtJS 구조 생성하여 연동테스트 해보기 (1) | 2014.11.24 |
오랫만에 ExtJS 강좌 포스팅을 등록해보도록 하겠습니다.
지난 시간까지 ExtJS MVC 구조에 대하여 잡아보았습니다.
2014/11/26 - [웹개발강좌/ExtJS] - ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View+Controller 연동)
2014/11/26 - [웹개발강좌/ExtJS] - ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View/Controller + Model+Store 추가)
이번장에는 기존 연동되어있는 MVC 구조를 이용하여 DB와 연동하여
C : DB INSERT
R : DB SELECT
U : DB UPDATE
D : DB DELETE
작업을 수행해보도록 하겠습니다.
DB 연동에 대해서는 본인이 작업하는 환경에 맞추어 미리 연동을 해놓으시기 바라겠습니다.
저같은경우는 JSP 기반 SPRING Framework 를 이용하여 DB 연동을 하였습니다
DBMS는 MySQL을 이용하여 다음과 같은 구조의 테이블을 생성하였습니다.
CREATE TABLE `grid` ( `idx` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(100) DEFAULT NULL, `name` varchar(100) DEFAULT NULL, PRIMARY KEY (`idx`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
Oracle 혹은 MSSQL등 MySQL이 아닌 다른 DBMS에는
컬럼타입과 컬럼명만 맞추기만 하여 테이블 생성하시면 되겠습니다.
이어서 임의로 가상의 데이터 몇가지를 insert 해보도록 하겠습니다.
INSERT INTO grid(title,NAME) VALUES('제목1','이름1'); INSERT INTO grid(title,NAME) VALUES('제목2','이름2'); INSERT INTO grid(title,NAME) VALUES('제목3','이름3');
이어서 각 MVC 폴더구조는 다음과 같습니다.
그럼 각 MVC 파일들에 대한 코드를 간단하게 작성 및 설명을 해보도록 하겠습니다.
<!-- ExtJS 연동 관련 INCLUDE 파일들 --> <link rel="stylesheet" type="text/css" href="/resource/extjs/ext-theme-crisp-touch/build/resources/ext-theme-crisp-touch-all.css"/> <script type="text/javascript" src="/resource/extjs/ext-all.js"></script> <script type="text/javascript" src="/resource/extjs/ext-theme-crisp-touch/build/ext-theme-crisp-touch.js"></script> <script type="text/javascript" src="/resource/extjs/ext-theme-crisp-touch/build/ext-theme-crisp-touch.js"></script> <!-- ExtJS MVC 연동 파일 --> <script type="text/javascript" src="/resource/mvc.js"></script>
별도의 HTML코드는 필요없습니다.
<head></head> 태그 사이에 include 해주도록 합니다.
Ext.application({ name: 'mvc_study', appFolder : '/resource/mvc_study', controllers: [ 'MvcController' ], autoCreateViewport: true });
MVC 선언 시
appFolder : mvc 구조를 잡기위한 최상단 루트폴더지정 없을시 "/app" 이 default
controllers : 컨트롤러 파일 설정을 위한 설정
Ext.define('mvc_study.view.Viewport', { extend: 'Ext.container.Viewport', layout : 'border', items : [{ region : 'center', xtype : 'customGrid' }], initComponent: function() { this.callParent(); } });
MVC에서 최초 LOAD의 시작파일
※ 기존 Ext.create와 같은 구조입니다.
다른점이 있다면, renderTo를 별도로 해주실 필요가 없으며
Viewport 클래스를 상속받는 것 외에는 없습니다.
구조는 이전에 했던 방식과 동일합니다.
이어서 xtype이 customGrid인 컴포넌트를 지정을 하였는데
컴포넌트는 기본으로 제공하는 컴포넌트가 아닌 사용자지정 컴포넌트입니다.
그럼 customGrid에 대하여 정의를 해보도록 합니다.
Ext.define('mvc_study.view.grid.CustomGrid', { extend: 'Ext.grid.Panel', //xtype에 들어가는 컴포넌트 명칭이다. //widget. << 이부분을 제외한 나머지명칭을 xtype에 선언 해주면 됨 alias : 'widget.customGrid', title : '그리드 CRUD', //로우에디터를 사용하기 위한 플러그인 설정 plugins: [Ext.create('Ext.grid.plugin.RowEditing', { clicksToMoveEditor: 1, autoCancel: false })], columns : [ //idx 컬럼은 수정이불가하므로 editor 속성을 제거 //그외 title,name에만 editor 속성 허용 { text : '번호', flex : 1, dataIndex : 'idx' },{ text : '제목', flex : 1, dataIndex : 'title', editor: { xtype: 'textfield' } },{ text : '이름', flex : 1, dataIndex : 'name', editor: { xtype: 'textfield' } }], store : 'GridStore', fbar : [{ xtype : 'button', text : '추가', handler : function(btn){ //GridModel var rec = Ext.create('mvc_study.model.GridModel',{ title: '', name : '' }); //로우 추가 btn.up("grid").getStore().insert(0,rec); //에디트 포커스 btn.up("grid").plugins[0].startEdit(0, 0); } },{ xtype : 'button', text : '삭제', handler : function(btn){ //선택된 로우 삭제 btn.up("grid").getStore().remove(btn.up("grid").getSelectionModel().getSelection()); } },{ xtype : 'button', text : '적용', handler : function(btn){ //각 row 마다 싱크를 맞춰주면서 btn.up("grid").getStore().sync({ //성공시 success: function( response ) { //그리드 select btn.up("grid").getStore().load(); } }); } }], initComponent: function() { this.callParent(); } });
이어서 customGrid의 config속성중
store에 선언되어있는
GridStore에 대하여 정의를 해보도록 합니다.
Ext.define('mvc_study.store.GridStore', { extend: 'Ext.data.Store', model: 'mvc_study.model.GridModel', //페이지 로드시 자동으로 READ 조회 autoLoad : true, proxy: { type: 'ajax', api: { //등록페이지 create : '/insertData', //조회페이지 read: '/listData', //수정페이지 update : '/updateData', //삭제페이지 destroy : '/deleteData' }, //select 옵션 reader: { type: 'json', successProperty: 'success', //응답받는 json object의 최상단 key값(SELECT 구문) //{ // data : 'value' //} rootProperty: 'items' }, //create,update,delete 옵션 writer: { type: 'json', //그리드 row의 모든값 전송 writeAllFields: true, //필수속성값 encode : true, //문자열로 넘어가는 서버 parameter값 json object의 최상단 key값(INSERT/UPDATE/DELETE 구문) //java 기준 : request.getParameter("data"); rootProperty: 'data' } } });
store는 기존포스팅을 따라오셨던 분들이시라면
크게 변한 부분은 없을 것입니다.
변경된 점이 있다면
proxy에 api부분에 (create/read/update/destroy) 속성과
writer 속성이 추가된것이 전부입니다.
주석으로 설명 대체를 하도록 하겠습니다 ^^ㅋㅋ
다음은 store에 설정한
model 속성에 정의된 GridModel에 대한 코드를 작성해보도록 합니다.
Ext.define('mvc_study.model.GridModel', { extend: 'Ext.data.Model', fields: ['idx','title','name'] });
모델을 생략하고 fields 속성을 데이터스토어에 정의를 해주셔도 무관하나
MVC에 관련된 내용이므로 MODEL에 fields 속성을 정의하였습니다.
화면에 대한 정의는 완료되었으나
뷰를 화면에 표출을 시키기 위하여 컨트롤러 파일을 다음과 같이 작성합니다.
Ext.define('mvc_study.controller.MvcController', { extend: 'Ext.app.Controller', stores : ['GridStore'], views: ['grid.CustomGrid'], init: function() { this.control(); } });
실질적으로 그리드 툴바들에 대한 버튼 컨트롤을 위하여
각 refs 라는 속성내에 버튼을 정의후 클릭이벤트에 대하여 기능을 구현하여야 하겠지만
이부분에 대해서는 다음 장에 그리드 페이징 및 컨트롤러 사용에 대하여 설명을 진행하겠습니다.
마지막으로 데이터 스토어에서 정의된 각각의 데이터통신을 하는 URL에 대한 샘플 코드를 작성하도록 하겠습니다.
서버페이지는 Spring MVC + Mybatis 를 이용하여 출력하며
JSON 파싱부분은 Jackson JSON을 이용하였습니다.
PHP 및 ASP 를 사용하시는 분들은 별도로 코드에 대한 설명을 파악 후
JSON REQUEST/RESPONSE 구조만 맞춰주시면 동일한 결과를 얻으실 수 있습니다.
/** * response json 결과값은 다음처럼 나와야 합니다. * {"items":[ * {"title":"제목3","idx":24,"name":"이름3"}, * {"title":"제목2","idx":23,"name":"이름2"}, * {"title":"제목1","idx":22,"name":"이름1"}], * "success":true} */ //list logic @RequestMapping("/listData") public @ResponseBody Map<String , Object> listData(HttpServletRequest request) throws SQLException { Map<String, Object> map = new HashMap<String, Object>(); //DB 목록 조회 ArrayList<Map<String, Object>> list = dao.listData(); //데이터스토어에 reader -> successPropery값과 맞춰줌 (true/false) map.put("success", true); //데이터스토어에 reader -> rootProperty값과 맞춰줌 //DB목록값에 대한 JSON KEY값은 items가 되어야 한다 map.put("items", list); return map; } /** * CREATE / UPDATE / DELETE 에 대한 JSON REQUEST 및 RESPONSE에 대한 구조는 동일 * 다른점은 DB통신하는 부분만 변경해주면 됨 * REQUEST 구조 * jsp = request.getParameter("data"); * php = $_REQUEST['data'] * asp = <%=request("data") %> * 위와같이 하면 JSON문자열 데이터로 넘어옵니다. * 넘어온 문자열을 각 언어에 맞게끔 string to object로 변환하는 방식을 이용합니다. * 제가 사용한 Jackson JSON라이브러리는 단일 object, 배열 object별로 구분을 해주어야 하므로 * 넘어온 json 문자열에 맨 앞 표시에 따라 구분을 하였습니다. * * RESPONSE 구조 * DB가 정상적으로 등록/수정/삭제 되었다 가정하고 * {success : true} * 라는 JSON OBJECT를 RESPONSE 해줍니다. */ //insert logic @RequestMapping("/insertData") public @ResponseBody Map<String , Object> insertData(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException, SQLException { Map<String, Object> hmap = new HashMap<String, Object>(); hmap.put("success", true); String data = request.getParameter("data"); ObjectMapper mapper = new ObjectMapper(); if(data.substring(0,1).equals("{")) { Map<String, Object> map = mapper.readValue(data, Map.class); dao.insertData(map); } else { ArrayList<Map<String, Object>> list = (ArrayList<Map<String, Object>>) mapper.readValue(data, List.class); if(list != null && list.size() > 0) { //처음부터 등록시 마지막 등록한게 최우선 등록하게 되므로 거꾸로 for문을 돌림 for(int i= list.size() -1 ; i >= 0; i--) { dao.insertData(list.get(i)); } } } return hmap; } //update logic @RequestMapping("/updateData") public @ResponseBody Map<String , Object> updateData(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException, SQLException { Map<String, Object> hmap = new HashMap<String, Object>(); hmap.put("success", true); String data = request.getParameter("data"); ObjectMapper mapper = new ObjectMapper(); if(data.substring(0,1).equals("{")) { Map<String, Object> map = mapper.readValue(data, Map.class); dao.updateData(map); } else { ArrayList<Map<String, Object>> list = (ArrayList<Map<String, Object>>) mapper.readValue(data, List.class); if(list != null && list.size() > 0) { //upate 순서는 상관없으므로 for(Map<String, Object> map : list) { dao.updateData(map); } } } return hmap; } //delete logic @RequestMapping("/deleteData") public @ResponseBody Map<String , Object> deleteData(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException, SQLException { Map<String, Object> hmap = new HashMap<String, Object>(); hmap.put("success", true); String data = request.getParameter("data"); ObjectMapper mapper = new ObjectMapper(); if(data.substring(0,1).equals("{")) { Map<String, Object> map = mapper.readValue(data, Map.class); dao.deleteData(map); } else { ArrayList<Map<String, Object>> list = (ArrayList<Map<String, Object>>) mapper.readValue(data, List.class); if(list != null && list.size() > 0) { //delete 순서는 상관없으므로 for(Map<String, Object> map : list) { dao.deleteData(map); } } } return hmap; }
각 DB호출하는 쿼리로직은 다음과 같습니다.
<select id="listData" resultType="java.util.Map"> SELECT idx,title, name FROM grid ORDER BY idx DESC </select> <insert id="insertData" parameterType="java.util.Map"> INSERT INTO grid(title,name) VALUES(#{title},#{name}) </insert> <update id="updateData" parameterType="java.util.Map"> UPDATE grid SET title = #{title}, name = #{name} WHERE idx = #{idx} </update> <delete id="deleteData" parameterType="java.util.Map"> DELETE FROM grid WHERE idx = #{idx} </delete>
이제 ExtJS MVC를 이용한 "GRID CRUD" 관련 코드작성은 완료되었습니다.
이제 실행을 해보도록 하겠습니다.
위 데이터 3개는 임의로 테이블 생성 후
insert한 데이터에 대한 값을 출력한 결과입니다.
추가 버튼 클릭 후 제목과 이름에 textfield 로 원하는 값을 입력 후
UPDATE 버튼을 클릭합니다.
※ update 버튼 클릭한다고 데이터 통신이 되지 않습니다.
임의로 화면상에 쌓아두고 있는 상태입니다. ※
추가버튼을 이용하여 가상의 데이터 2개를 삽입 후
기존 데이터를 선택하여 각 컬럼을 수정하였습니다.
기존 데이터를 선택 후 삭제버튼을 클릭한 최종 화면입니다.
화면에 보시다시피 기존 데이터를 제외한 나머지에 각 컬럼 좌측상단을 보시면
빨칸화살표같은 것이 있는데 이부분은 임의로 등록이 되었거나 수정이 되었다는 뜻입니다.
그럼 이제 적용 버튼을 클릭하여 데이터 통신이 일어난 후의 결과 화면을 보도록 하겠습니다.
신규로 넣었던 데이터에 대한 번호시퀀스 값이 자동으로 적용되며
수정된 값도 정상적으로 반영되어 최종값이 로드되었습니다.
다음장은 기존 소스에 이어 그리드 페이징 및 각 버튼에 대한 기능들을
컨트롤러에 담아보도록 하겠습니다.
by 개발로짜
ExtJS 강좌 - ExtJS5 MVC 구조를 이용한 간단 그리드 CRUD 알아보기(2) (5) | 2015.01.07 |
---|---|
Spring @ResposeBody를 이용하여 JSON Response 할때 IE에서 다운로드현상 해결법 (4) | 2014.12.07 |
ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View/Controller + Model+Store 추가) (0) | 2014.11.26 |
ExtJS 강좌 - ExtJS5 MVC 구조 잡아보기(View+Controller 연동) (2) | 2014.11.26 |
ExtJS 강좌 - Sencha CMD로 ExtJS 구조 생성하여 연동테스트 해보기 (1) | 2014.11.24 |