블로그 이미지

카테고리

데꾸벅 (194)
Publisher (39)
Scripter (97)
Programmer (1)
Designer (30)
Integrator (18)
Pattern Searcher (4)
News (2)
강좌 및 번역 (3)

최근에 올라온 글

최근에 달린 댓글

'editor grid'에 해당되는 글 2건

  1. 2009.03.31 extjs RowAction 붙이기 1
  2. 2008.04.07 ExtJS를 이용한 EditorGrid 붙이기 2


기본적으로 grid의 View에 editor와 같이 다른 컴포넌트를 붙이기는 기존 소스보다 컴포넌트를 붙이는 소스가 더 많이 들어가는 경우가 있다.
데꾸벅의 경우도 프로젝트중 각각의 그리드 Row마다 progress bar를 붙여야 하는 경우가 생겼었는데..
포럼글을 뒤지다가 다음과 같은 좋은 사용자 플러그인이 있어 분석을 위해 소스를 까 보았다.



위 그림에서 보는바와 같이 그리드위에 버튼을 만들어 올릴때 new Ext.button이 아닌 new Ext.Action을 사용하여 사용자 플러그인을 사용한 소스이다.
소스 API  및 관련 포럼글 

HTML
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <link rel="stylesheet" type="text/css" href="./css/icons.css">
 <link rel="stylesheet" type="text/css" href="./css/Ext.ux.grid.RowActions.css">
    <link rel="stylesheet" type="text/css" href="../../ext/ext-2.2/resources/css/ext-all.css" />
    <script type="text/javascript" src="../../ext/ext-2.2/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../../ext/ext-2.2/ext-all.js"></script>
 <script type="text/javascript" src="./js/Ext.ux.grid.RowActions.js"></script>
 <script type="text/javascript" src="./js/Ext.ux.Toast.js"></script>
 <script type="text/javascript" src="rowactions.js"></script>
</head>
<body></body>
</html>





JS

Ext.BLANK_IMAGE_URL = '';
Ext.ns('Example');
Example.version = '1.0';

Example.Grid = Ext.extend(Ext.grid.GridPanel, {

  initComponent:function() {

   // Create RowActions Plugin
   this.action = new Ext.ux.grid.RowActions({
    header:'Actions'
   ,autoWidth:true
   ,keepSelection:true
   ,actions:[{
     iconIndex:'action1'
    ,qtipIndex:'qtip1'
    ,iconCls:'icon-open'
    ,tooltip:'Open'
   },{
     iconCls:'icon-wrench'
    ,tooltip:'Configure'
    ,qtipIndex:'qtip2'
    ,iconIndex:'action2'
    ,hideIndex:'hide2'
   },{
     iconIndex:'action3'
    ,qtipIndex:'qtip3'
    ,iconCls:'icon-user'
    ,tooltip:'User'
    ,style:'background-color:yellow'
   }]
   ,groupActions:[{
     iconCls:'icon-del-table'
    ,qtip:'Remove Table'
   },{
     iconCls:'icon-add-table'
    ,qtip:'Add Table - with callback'
    ,callback:function(grid, records, action, groupId) {
     Ext.ux.Message.msg('Callback: icon-add-table'
         , 'Group: <b>{0}</b>, action: <b>{1}</b>, records: <b>{2}</b>'
         , groupId
         , action
         , records.length);
    }
   },{
     iconCls:'icon-graph'
    ,qtip:'View Graph'
    ,align:'left'
   }]
   ,callbacks:{
    'icon-plus':function(grid, record, action, row, col) {
     Ext.ux.Message.msg('Callback: icon-plus'
         , 'You have clicked row: <b>{0}</b>, action: <b>{0}</b>'
         , row
         , action);
    }
   }
  });

  this.action.on({
   action:function(grid, record, action, row, col) {
    Ext.ux.Message.msg('Event: action', '클릭한 Row: <b>{0}</b>, 액션: <b>{1}</b>'
        , row
        , action);
   }
   ,beforeaction:function() {
    Ext.ux.Message.msg('Event: beforeaction', '핸들러에서 false반환시 액션취소.');
   }
   ,beforegroupaction:function() {
    Ext.ux.Message.msg('Event: beforegroupaction', '핸들러에서 false반환시 액션취소');
   }
   ,groupaction:function(grid, records, action, groupId) {
    Ext.ux.Message.msg('Event: groupaction', 'Group: <b>{0}</b>, action: <b>{1}</b>, records: <b>{2}</b>', groupId, action, records.length);
   }
  });

  Ext.apply(this, {
    store:new Ext.data.Store({
    reader:new Ext.data.JsonReader({
      id:'company'
     ,totalProperty:'totalCount'
     ,root:'rows'
     ,fields:[
      {name: 'company'}
        ,{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
        ,{name: 'industry'}
        ,{name: 'desc'}
        ,{name: 'action1', type: 'string'}
        ,{name: 'action2', type: 'string'}
        ,{name: 'action3', type: 'string'}
        ,{name: 'qtip1', type: 'string'}
        ,{name: 'qtip2', type: 'string'}
        ,{name: 'qtip3', type: 'string'}
        ,{name: 'hide2', type: 'boolean'}
     ]
    })
    ,proxy:new Ext.data.HttpProxy({url:'jsonData.json'})
    ,sortInfo:{field:'company', direction:'ASC'}
    ,listeners:{
     load:{scope:this, fn:function() {
      this.getSelectionModel().selectFirstRow();
     }}
    }
   })
   ,columns:[
    {id:'company',header: "Company", width: 40, sortable: true, dataIndex: 'company'}
    ,{header: "Industry", width: 20, sortable: true, dataIndex: 'industry'}
    ,{header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
    ,this.action
   ]
   ,plugins:[this.action]
   ,loadMask:true
   ,viewConfig:{forceFit:true}
  });

  this.bbar = new Ext.PagingToolbar({
    store:this.store
   ,displayInfo:true
   ,pageSize:10
  });

  Example.Grid.superclass.initComponent.apply(this, arguments);
 }


 ,onRender:function() {
  Example.Grid.superclass.onRender.apply(this, arguments);
  this.store.load({params:{start:0, limit:10}});
 }
});

//컴포넌트 등록
Ext.reg('techbuggrid', Example.Grid);

Ext.onReady(function() {
    Ext.QuickTips.init();

    var win = new Ext.Window({
         width:600
  ,minWidth:320
        ,id:'agwin'
        ,height:400
        ,layout:'fit'
        ,border:false
  ,plain:true
        ,closable:false
        ,title:"그리드 Row Action 처리하기"
  ,items:{xtype:'techbuggrid',id:'actiongrid'}
    });
    win.show();
});




사용자 플러그인.JS

Ext.ns('Ext.ux.grid');
if('function' !== typeof RegExp.escape) {
 RegExp.escape = function(s) {
  if('string' !== typeof s) {
   return s;
  }
  return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1');
 };
}

Ext.ux.grid.RowActions = function(config) {
 Ext.apply(this, config);
 this.addEvents(
   'beforeaction'
  ,'action'
  ,'beforegroupaction'
  ,'groupaction'
 );
 Ext.ux.grid.RowActions.superclass.constructor.call(this);
};

Ext.extend(Ext.ux.grid.RowActions, Ext.util.Observable, {
  actionEvent:'click'
 ,autoWidth:true
 ,dataIndex:''
 ,header:''
 ,keepSelection:false
 ,menuDisabled:true
 ,sortable:false
 ,tplGroup:
   '<tpl for="actions">'
  +'<div class="ux-grow-action-item<tpl if="\'right\'===align"> ux-action-right</tpl> '
  +'{cls}" style="{style}" qtip="{qtip}">{text}</div>'
  +'</tpl>'
 ,tplRow:
   '<div class="ux-row-action">'
  +'<tpl for="actions">'
  +'<div class="ux-row-action-item {cls} <tpl if="text">'
  +'ux-row-action-text</tpl>" style="{hide}{style}" qtip="{qtip}">'
  +'<tpl if="text"><span qtip="{qtip}">{text}</span></tpl></div>'
  +'</tpl>'
  +'</div>'
 ,hideMode:'visiblity'
 ,widthIntercept:4
 ,widthSlope:21
 ,init:function(grid) {
  this.grid = grid;
  if(!this.tpl) {
   this.tpl = this.processActions(this.actions);
  }
  if(this.autoWidth) {
   this.width =  this.widthSlope * this.actions.length + this.widthIntercept;
   this.fixed = true;
  }
  var view = grid.getView();
  var cfg = {scope:this};
  cfg[this.actionEvent] = this.onClick;
  grid.afterRender = grid.afterRender.createSequence(function() {
   view.mainBody.on(cfg);
   grid.on('destroy', this.purgeListeners, this);
  }, this);

  if(!this.renderer) {
   this.renderer = function(value, cell, record, row, col, store) {
    cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
    return this.tpl.apply(this.getData(value, cell, record, row, col, store));
   }.createDelegate(this);
  }

  if(view.groupTextTpl && this.groupActions) {
   view.interceptMouse = view.interceptMouse.createInterceptor(function(e) {
    if(e.getTarget('.ux-grow-action-item')) {
     return false;
    }
   });
   view.groupTextTpl =
     '<div class="ux-grow-action-text">' + view.groupTextTpl +'</div>'
    +this.processActions(this.groupActions, this.tplGroup).apply()
   ;
  }

  if(true === this.keepSelection) {
   grid.processEvent = grid.processEvent.createInterceptor(function(name, e) {
    if('mousedown' === name) {
     return !this.getAction(e);
    }
   }, this);
  }
  
 }
 ,getData:function(value, cell, record, row, col, store) {
  return record.data || {};
 }

 ,processActions:function(actions, template) {
  var acts = [];

  Ext.each(actions, function(a, i) {
   if(a.iconCls && 'function' === typeof (a.callback || a.cb)) {
    this.callbacks = this.callbacks || {};
    this.callbacks[a.iconCls] = a.callback || a.cb;
   }

   var o = {
     cls:a.iconIndex ? '{' + a.iconIndex + '}' : (a.iconCls ? a.iconCls : '')
    ,qtip:a.qtipIndex ? '{' + a.qtipIndex + '}' : (a.tooltip || a.qtip ? a.tooltip || a.qtip : '')
    ,text:a.textIndex ? '{' + a.textIndex + '}' : (a.text ? a.text : '')
    ,hide:a.hideIndex
     ? '<tpl if="' + a.hideIndex + '">'
      + ('display' === this.hideMode ? 'display:none' :'visibility:hidden') + ';</tpl>'
     : (a.hide ? ('display' === this.hideMode ? 'display:none' :'visibility:hidden;') : '')
    ,align:a.align || 'right'
    ,style:a.style ? a.style : ''
   };
   acts.push(o);

  }, this);

  var xt = new Ext.XTemplate(template || this.tplRow);
  return new Ext.XTemplate(xt.apply({actions:acts}));

 }
 ,getAction:function(e) {
  var action = false;
  var t = e.getTarget('.ux-row-action-item');
  if(t) {
   action = t.className.replace(/ux-row-action-item /, '');
   if(action) {
    action = action.replace(/ ux-row-action-text/, '');
    action = action.trim();
   }
  }
  return action;
 }
 ,onClick:function(e, target) {

  var view = this.grid.getView();

  var row = e.getTarget('.x-grid3-row');
  var col = view.findCellIndex(target.parentNode.parentNode);
  var action = this.getAction(e);

  if(false !== row && false !== col && false !== action) {
   var record = this.grid.store.getAt(row.rowIndex);

   if(this.callbacks && 'function' === typeof this.callbacks[action]) {
    this.callbacks[action](this.grid, record, action, row.rowIndex, col);
   }

   if(true !== this.eventsSuspended && false === this.fireEvent('beforeaction', this.grid, record, action, row.rowIndex, col)) {
    return;
   }
   else if(true !== this.eventsSuspended) {
    this.fireEvent('action', this.grid, record, action, row.rowIndex, col);
   }

  }

  t = e.getTarget('.ux-grow-action-item');
  if(t) {
   var group = view.findGroup(target);
   var groupId = group ? group.id.replace(/ext-gen[0-9]+-gp-/, '') : null;

   var records;
   if(groupId) {
    var re = new RegExp(RegExp.escape(groupId));
    records = this.grid.store.queryBy(function(r) {
     return r._groupId.match(re);
    });
    records = records ? records.items : [];
   }
   action = t.className.replace(/ux-grow-action-item (ux-action-right )*/, '');

   if('function' === typeof this.callbacks[action]) {
    this.callbacks[action](this.grid, records, action, groupId);
   }

   if(true !== this.eventsSuspended && false === this.fireEvent('beforegroupaction', this.grid, records, action, groupId)) {
    return false;
   }
   this.fireEvent('groupaction', this.grid, records, action, groupId);
  }
 }

});

Ext.reg('rowactions', Ext.ux.grid.RowActions);




요기 괜찮은 사용자 플러그인도 함 보세요





















'Scripter > EXTJS' 카테고리의 다른 글

Extjs Core 3.0 Beta 릴리즈  (4) 2009.04.07
Examples Of ExtJS in Action  (2) 2009.03.31
extjs 2.2의 IE에서 iframe document load 버그패치  (0) 2009.01.21
Extjs 3.0 Roadmap  (10) 2008.11.12
Ext2.2 Release  (11) 2008.08.07
Post by 넥스트리소프트 데꾸벅(techbug)
, |
사내(넥스트리)위키에 올렸던 자료를 다시 정리하여 포스팅한다.

일반그리드와 달리 에디터그리드의 경우 해당 Cell에 해당하는 값을 변경할수 있다. 각각의 선택된 셀값과 추가하는 방법 및 해당 값들을 셋팅하는 방법, ActionComplete후 dirtyFlag를 삭제하는 방법등에 대해서 알아보자! 에디터 그리드는 이미 이전장에서 사용되었던 기본그리드를 사용하였으므로 반드시 이전장을 참조하도록 한다. 추가적으로 FormPanel에 대하여 미리 알아 보도록 한다.

최종소스 :

사용자 삽입 이미지


basicGrid.html

<html>
<head>
<title>Basic Grid</title>
<link rel="stylesheet" type="text/css" href="http://techbug.tistory.com/resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
<script type="text/javascript" src="basicGrid.js"></script>
</head>
<body id="basicGridBody">
<div id="DIV_GRID_HERE"></div>
</body>
</html>

basicGrid.js

BasicGridClass = function() {
    return {
        init : function() {
            // 데이타 스토어 정의
            this.store = new Ext.data.Store( {
                proxy : new Ext.data.HttpProxy( {
                    url : 'basicGrid.json'
                }),
                sortInfo : {
                    field : 'price',
                    direction : "DESC"
                },
                reader : new Ext.data.JsonReader( {
                    root : 'testData'
                }, this.myRecordObj = Ext.data.Record.create([ {
                    name : 'company',
                    type : 'string',
                    mapping : 'company'
                }, {
                    name : 'price',
                    type : 'float',
                    mapping : 'price'
                }, {
                    name : 'change',
                    type : 'float',
                    mapping : 'change'
                }, {
                    name : 'pctChange',
                    type : 'float',
                    mapping : 'pctChange'
                }, {
                    name : 'lastChange',
                    type : 'date',
                    dateFormat : 'n/j h:ia',
                    mapping : 'lastChange'
                }]))
            });
            this.grid = new Ext.grid.EditorGridPanel( {
                store : this.store,
                columns : [ {
                    id : 'company',
                    header : "Company",
                    width : 160,
                    sortable : true,
                    dataIndex : 'company',
                    editor : new Ext.form.TextField( {
                        allowBlank : true
                    })
                }, {
                    header : "Price",
                    width : 75,
                    sortable : true,
                    renderer : 'usMoney',
                    dataIndex : 'price',
                    editor : new Ext.form.NumberField( {
                        allowBlank : false,
                        allowNegative : false
                    })
                }, {
                    header : "Change",
                    width : 75,
                    sortable : true,
                    dataIndex : 'change'
                }, {
                    header : "% Change",
                    width : 75,
                    sortable : true,
                    dataIndex : 'pctChange'
                }, {
                    header : "Last Updated",
                    width : 85,
                    sortable : true,
                    renderer : Ext.util.Format.dateRenderer('m/d/Y'),
                    dataIndex : 'lastChange',
                    editor : new Ext.form.DateField( {
                        allowBlank : false,
                        minValue : '08/21/00',
                        disabledDays : [0, 2, 6],
                        disabledDaysText : '이날짜는 선택안되요'
                    })
                }

                ],
                stripeRows : true,
                autoExpandColumn : 'company',
                loadMask : {
                    msg : '데이타 로드중'
                },
                clicksToEdit : 1, // Edit하기 위해 Cell을 클릭해야 하는 횟수 (최대2, 최소1)
                sm : new Ext.grid.RowSelectionModel( {
                    singleSelect : true
                }),
                view : new Ext.grid.GridView( {
                    forceFit : true,
                    enableRowBody : true,
                    emptyText : 'No Record found'
                }),
                height : 350,
                width : 1024,
                title : '기본 그리드',
                tbar : [
                        {
                            text : '저장',
                            scope : this,
                            handler : this.saveAllChanges
                        },
                        '-',
                        {
                            text : '추가',
                            scope : this,
                            handler : this.addRecord
                        },
                        '-',
                        {
                            text : '삭제',
                            scope : this,
                            handler : function() {
                                var selectedKeys = this.grid.selModel.selections.keys;
                                if (selectedKeys.length > 0) {
                                    Ext.MessageBox.confirm('확인',
                                            '정말 삭제할래요? 삭제하면 복구안돼요..',
                                            this.deleteRecord, this);
                                } else {
                                    alert('삭제할 Row를 선택하세요');
                                }

                            }
                        }, '-', {
                            text : '새로고침',
                            scope : this,
                            handler : function() {
                                this.store.reload()
                            }
                        }]
            });

            this.grid.render('DIV_GRID_HERE');
            this.store.load();
            this.grid.on('afteredit', this.afterCellEditEventHandler, this); // Cell을
            // 변경후
            // 일어나는
            // 이벤트
        },

        // CEll변경후 일어나는 이벤트
        afterCellEditEventHandler : function(editEvent) { // Cell을 변경후 일어나는
            // 이벤트
            var gridField = editEvent.field;
            var gridValue = editEvent.value;
            editEvent.record.set('company', editEvent.record.get('company')
                    + '변경필트:' + gridField + '변경된값' + gridValue);
            this.updateCell(editEvent);
        },

        // 삭제하는 루틴
        deleteRecord : function(btn) {
            if (btn == 'yes') {
                var selectedRows = this.grid.selModel.selections.items;
                var selectedKeys = this.grid.selModel.selections.keys;
                var selectedRecord = this.grid.selModel.getSelected();
                alert(selectedRecord.get('company') + '\n' + selectedRows
                        + '\n' + selectedKeys + '\n지우는 Ajax Call 후에 다시 리로드한다.');
                this.store.reload();
            }
        },

        // 새로운 Row를 추가하기
        addRecord : function(btn) {
            var r = new this.myRecordObj( {
                // this.myRecordObj는
                // this.store.reader의 Record Field를
                // 말함.
                company : '새 회사명',
                price : 0.00,
                change : 0.00,
                pctChange : 0.00,
                lastChange : new Date(),
                newRecord : 'yes', // Update할때 트리거로 이용하기 위해서
                id : 0
            });
            this.grid.stopEditing();
            this.store.insert(0, r);
            this.grid.startEditing(0, 0); // 추가할 rowIndex, colIndex 위치
        },

        // 수정된 Cell만 저장하기
        updateCell : function(editEvent) {
            var isNewRecord = editEvent.record.data.newRecord;
            // 업데이트할때 사용될
            // 트리거('yes'면 새로운 레코드)
            /** ** AJAX 통신 모듈 들어가는곳 ***** */

            // DB를 성공적으로 업데이트 후 처리할 루틴
            if (isNewRecord == 'yes') {
                // 저장한후 새로운 레코드가 아님을 표시
                editEvent.record.set('newRecord', 'no');
                // isDirty Flag 없애기
                this.store.commitChanges();
            } else {
                this.store.commitChanges();
            }

            // 잘못됐을경우는 this.sotre.rejectChanges(); 로 리복한다.
            this.store.rejectChanges();

        },

        //변경된것들 모두 저장하기
        saveAllChanges : function() {
            var modifyRecords = this.store.getModifiedRecords(); //수정된 레코드 모두 찾기
            var modifyLen = modifyRecords.length;
            if (modifyLen > 0) {
                for (var i = 0;i < modifyLen; i++) {
                    /* 각 Row마다 AJAX Call을 하거나 배열로 모두 넘기는 Ajax Call Method가 들어간다.*/
                    var modifyCompany = modifyRecords[i].get('company')
                }
            }

        }

    }
}();
Ext.EventManager.onDocumentReady(BasicGridClass.init, BasicGridClass, true);






 






'Scripter > EXTJS' 카테고리의 다른 글

Extjs Qtips 사용하기  (2) 2008.04.16
Extjs 기본레이아웃에 각종 패널붙이기  (12) 2008.04.16
ExtJS 로드맵  (0) 2008.04.01
ExtJS를 이용한 Password Meter  (0) 2008.04.01
Ext JS Ext.ux.YoutubePlayer  (0) 2008.03.29
Post by 넥스트리소프트 데꾸벅(techbug)
, |