파일을 업로드할 때에는 form의 enctype을 multipart/form-data 타입으로 지정해야 한다.
2.x의 ExtJS의 FormPanel에서는 이를 지정할 수 없어 별도의 플러그인인을 사용해오곤 했는데
3.x에서는 FormPanel에 FileUpload라는 속성이 추가되어 파일업로드를 할 수 있게 되었다.

new Ext.FormPanel({
    fileUpload: true,
    baseParams: {
        foo: 'bar'
    },
    url: 'myProcess.do',
    items: [{
        xtype: 'fileuploadfield',
        name: 'upload'
    }],
    buttons: [{
        text: 'Save',
        handler: function(){
            var fp = this.ownerCt.ownerCt,
                form = fp.getForm();
            if (form.isValid()) {
                form.submit();
            }
        }
    }]
});

업로드 성공시 
{'success':true}
 라는 JSON 객체를 반환하도록 구현하였는데.

아무런 반응도 없다. 반환하는 result 값으로 failure와 error도 만들어봐도 수신하지 못한다.
확인된 스크립트 에러는 JSON 유형에 맞지 않아 파싱할 수 없단다. -_-a
확인해보니 반환된 값은
 
<PRE>{'success':true}</PRE>

허걱. 갑자기 무슨 PRE 태그란 말인가? 덕분에 한참 삽질한 덕분에 알게된 사실.

기본적으로 BasicForm은 Ext.form.Action.Submit 인스턴스를 이용하여 ajax 를 통한 submit을 수행하는데
FileUpload 옵션을 사용하는 경우 Ajax submission이 수행되지 않기 때문에 XMLHttpRequests 를 받지 못하게 되기 때문에
발생한 문제....

해결방법은 두가지.
Ext.form.Action.Submit 인스턴스가 아닌 Ext.Ajax.request 로 수행되도록 하던지 (standardSubmit 의 config 옵션을 사용하는 방법은 FileUpload 옵션이 우선되어 적용되지 않는다.)
또다른 방법으로 Hidden 속성인 iFrame을 사용하여 target을 XMLHttpRequests가 아닌 수신받는 XMLHttpRequests를 참조하는별도의 페이지로 지정하면 된다.

예를 들어 result.jsp라는 것을 동적으로 XMLHttpRequests들  수신하게 만들어두고 target을 result.jsp로 지정하면
PRE 태그가 빠진 정상적인 JSON객체를 수신받을 수 있게 된다.

그냥 기존대로 쓸껄 하는 생각이 들지만 머 표현의 가능성은 선택이니..몰랐던 것을 알게된 것으로 만족하자....화이팅~
 

[ExtJS 3.2] 이벤트 핸들러 등록하기

WEB2.0/ExtJS | 2010. 4. 23. 10:20
Posted by 시반

간간이 맡게 되는 웹프로젝트 덕에 이번에 ExtJS를 2.*에서 3.2 버젼으로 바꿔보았습니다.
마지막으로 볼때만해도 3.0 core 베타가 막 나올 때였는데 벌써 3.2가 나왔다니.
ExtJS Designer 라는 UI 툴도 생겨있던데 그리 비싸지는 않지만 유료라는 점..
솔직히 얼마 되지 않은 가격이기에 구매해볼까 알아봤는데 어느 분의 블로그에서처럼 구매하기도 쉽지많은 않거니와
데모버젼에서는 다소 버그가 있는 듯 확인이 되서 구매는 보류를...그리고 사이트는 왜이리 느려진건지...

다행히 기존 코드와 대부분 호환되는 거라 다행이었고.
이전버젼에서 나왔던 버그들도 이젠 거의 해결된 듯 보였다.(2.*를 쓸땐 별도의 버그패치파일을 만들어 사용)
당시 3.0 베타를 도입하지 않았던 가장 큰 이유중의 하나인 Extjs의 iframe 지원 플러그인인 miframe도 버젼업되어
3.*을 지원하고 있었기에 크게 어려운 점은 없었네요 

몇몇 호환되지 않았던 플러그인도 함께 마이그레이션을 해주니 동작엔 무리가 없었을 뿐더러
오히려 그동안 자체적으로 만들었던 플러그인들을 3.x대에서 지원하는 기능으로 바꿔주니 더 깔끔해진듯..

덕분에 어떤점이 바뀌었을까 궁금해 기존 소스와 비교해보다 발견한 이벤트 핸들러 등록방법..
기존 코드에서는 이벤트 핸들러를 등록하는 방법으로 on을 사용해왔었는데요.

예를 들어
body 부분을 c라고 했을 때 이벤트, 호출이벤트함수,scope를 인자로 가지는 on을 사용하여 이벤트 핸들러를 정의하였습니다.
코드로 살펴보면 다음과 같습니다.         

var c = this.body;  
c.on("click", this.onClick, this);   

지금은 다음과 같이 바뀌어져 있네요.

this.mon(c,{scope:this, click:this.onClick});

별거 아닌 듯 보이는 이러한 이벤트 핸들러처리방법을 통해 ExtJS의 전반적인 성능개선을 하고 있는셈.
왜냐하면 기존의 이벤트 핸들러를 등록하는 방법인 on은 메모리 누수의 문제가 있었는데
그러한 문제를 해결한 방법이 Ext.Component의 mon을 이용한 이벤트 핸들러 처리방법입니다.

사실 이를 해결한 mon이 Ext.Component에 추가된 것은 3.x가 아닌 2.1 이후 부터이지만 
ExtJS의 컴포넌트의 기본 핸들러에서는 계속 사용되어 왔기에
결국 패치나 커스텀핸들러를 재등록하는 방법으로 사용해 왔었는데요

3.x에서는 Extjs 컴포넌트의 핸들러가

this.mon(this.someEl, 'click', this.onClick, this); 


와 같은 방법으로 모두 변경되어 있어 별도의 패치 없어도 다소의 성능개선을 노릴수 있다는 점이 좋아졌달까?
3.x는 2.x에서 크게 변경되었다기 보다 그동안 제기되어 왔던 소소한 문제점들에 대해
전반적으로 새로이 리뉴얼한 느낌이네요.
 

ExtJS 2.2x를 쓰는 경우 IE6에서 그리드 상단 메뉴의 아이콘이 아래의 그림처럼

제대로 표시되지 않는 버그가 남아 있슴을 이제사 알게 되었다.

솔직히 이 버그는 예전에 발견된 버그일뿐 아니라 2.2.1 버젼에서는 fix된 것으로 알고 있었던 터라..

IE7 이후 버젼에만 맞추고 테스트를 진행했었는데..혹여나..

다시 최신버젼을 받아봐도 IE6에서 위에 해당하는 버그가 발생하는 것을 확인할 수 있었다.

예전엔 IE7 이후버젼에 이런 증상이 있었는데 지금은 거꾸로 IE6에서 발생하다니..

 

해결 방법은 이전버젼에서 적용했던 버그 fix를 그대로 적용하면 된다.

 

.ext-ie .x-menu-item-icon {left: -24px;}

.ext-strict .x-menu-item-icon {left: 3px;}

.ext-ie6 .x-menu-item-icon {left: -24px;}

 을  css에 추가하면 된다.

 

이젠 IE6 버젼에서 정상적으로 돌아가는 것을 확인할 수 있을 것이다.

물론 IE7과  IE8, 파폭, 크롬에서도 정상작동 확인...

 

ExtJS에서 DateField를 사용할 때 IE8에서는 달력이 짤려나오는 문제가 있다.

 

그림처럼 달력이 토막나 보인다.

해결방법은 Ext.menu.Menu 클래스의 autoWidth 메소드를 수정하면 된다.

Ext.override(Ext.menu.Menu, {
    autoWidth : function(){
        var el = this.el, ul = this.ul;
        if(!el){
            return;
        }
        var w = this.width;
        if(w){
            el.setWidth(w);
        }else if(Ext.isIE && !Ext.isIE8){
            el.setWidth(this.minWidth);
            var t = el.dom.offsetWidth; // force recalc
            el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));
        }
    }
});

 

 

 

ExtJS에서 유용하게 사용하는 플러그인중 하나가 그리드에서 검색기능을 지원하는 searchField가 아닐까 싶다.

헌데 IE8에서는 아래 화면에서 처럼 정상적으로 표현되지 않는다.(동작은 한다..)

 

아니면 다음그림처럼 검색필드 부분이 아예 나오지 않는 경우도 있다.

 

알아보니 searchField가 문제가 아니라

클래스 내의 멤버변수로 사용하고 있던 TriggerField에서 문제가 있었다.

 

문제가 있는 코드의 위치는 아래....

 

Ext.form.TriggerField = Ext.extend(Ext.form.TextField, {
...
afterRender : function(){
    Ext.form.TriggerField.superclass.afterRender.call(this);
    var y;
    if(Ext.isIE && !this.hideTrigger && this.el.getY() != (y = this.trigger.getY())){

    // 위 라인에서 문제가 발생한다....
        this.el.position();
        this.el.setY(y);
    }
},


그럼 이제 수정을..이번에도 직접 코드를 수정하기 보다는 override해서 처리를...

Ext.override(Ext.form.TriggerField, {


 afterRender : function(){
        Ext.form.TriggerField.superclass.afterRender.call(this);
        var y;
        if (Ext.isIE && !this.hideTrigger && this.el.getY() !=

              (y = (!this.triggers?this.trigger.getY():this.triggers[1].getY()))) {
            this.el.position();
            this.el.setY(y);
        }
    }
});


 

 이제 아래처럼 정상적으로...ㅋㅋ

 

정말 IE8 은 골치 아픈 브라우저가 아닌가 싶다. 유독 혼자만 튀고 싶은 MS의 성격을 그대로 가지고 있는 듯 하다.

분명 브라우징 속도는 빨라진 듯 같다(하지만 MS에서 말하는 것처럼 다른 브라우저보다 빠르다는 느낌은...-_-a)

웹표준을 지향한다던 IE8, 하지만  호환성 테스트 중 최하위..더군다나 이전 버젼의 IE 나 타 사의 브라우저에는 정상적으로

작동하는데 유독 IE8에서만 동작이 안되는 페이지들도 있다. IE8만의 웹표준은 아닐까?

 

여하튼 ExtJS를 통해 개발하면서 발견한 또하나의 버그?

 

위 그림처럼 텍스트상자의 상단 부분의 외곽선이 보이지 않는다.

확인해 보니 2.x 버젼의 ExtJS를 사용한 경우 IE8에서만 발생하는 문제였다.

해결 방법은  

.ext-ie8 .x-form-text{
    margin: 0px 0px;
}

.ext-ie8 .x-form-trigger{
    top: 1px;
}

 을 추가해 주면 된다.

 

 

2.2.1 이상의 버젼의 ExtJS로 구현된 경우 IE8에서 그리드의 편집을 위해 셀을 클릭할때마다 왼쪽으로 GridBody가 스크롤되어  숨어버리는 버그가 있다. 솔직히 이 버그는 예전에 ExtJS를 2.2.1 으로 마이그레이션을 할 때 발견했던 부분이었는데 IE8에서와는 달리 Editable Grid에서 셀을 클릭할때 GridView.focusCell에서 버그가 발생하여 패널에  ScrollBar가 생기곤 했다.

생기곤 했다라는 말대로 항상 발생한 것은 아니고 그리드가  두개의 컬럼만 가지고 있는 경우나 GridBody의 width가 GridPanel의 width보다 작은 경우에는 발생하지 않았다.

 

다음은 IE8을 사용할 경우 앞서 말한 버그를 보여준다. Extjs의 샘플페이지 중 Editable Grid 페이지에서 셀을 클릭한 경우 스크롤이 생기면서 GridBody부분이 왼편으로 숨어버리는 화면이다. 아직 버그 패치는 안된거 같구 이후 수정되면 샘플페이지에서는 이런 화면은 안나오게 될 수도....

 



날짜필드를 수정하기 위해 클릭하는 순간 아래처럼....

 이 버그는 IE뿐만 아니라 크롬,파폭에서 동일한 증상이 발견은 되었지만 IE8처럼 아예 GridBody부분이 스크롤되어 숨겨지지는 않았던 터라 기냥 두었던 건데..이런 IE8에서만 이리 되다니...
어쩔수 없이 수정을...(귀차니즘...)

GridView 코드 부분을 직접 수정해도 되겠지만 오버라이드하는 구문으로 처리했으니 기존소스페이지에 포함시키기만 하면 된다. 코드는 첨부파일로....

 

 

 ExtJs 2.0에서는 괜찮았는데 2.1~2.2를 사용하는 경우

위의 그림처럼 체크박스를 사용할 때 boxLabel 부분이 정상적으로 표시되지 않은 경우가 있다.

(아니면 뒤쪽으로 몰린다던지..)

 

Ext.form.Checkbox 에 정의되어있는 getResizeEl에 다음과 같이 정의되어 있다.

 getResizeEl : function(){
        if(!this.resizeEl){
            this.resizeEl = Ext.isSafari ? this.wrap : (this.wrap.up('.x-form-element', 5) || this.wrap);
        }
        return this.resizeEl;
  }

이부분을 다음과 같이 수정한다.

getResizeEl : function(){
        return this.wrap;
},

아니면 호출하는 스크립트에서

Ext.override(Ext.form.Checkbox, {
        getResizeEl : function(){
                return this.wrap;
        }
});

 이렇게 Override 해서 사용하면 정상적으로 표시됨을 확인할 수 있다.

 

 

Grid에서 Tree로 Drag&Drop

WEB2.0/ExtJS | 2009. 1. 8. 17:53
Posted by 시반

ExtJS의 샘플예제를 보면 몇몇 DD(DragDrop) 샘플예제들을 볼 수 있다.

먼저 그리드에서 Drag&Drop을 사용하기 위해서는 

drag할 그리드에서  enableDragDrop옵션을 true로 해주고

ddGroup을 정의한후 (아래샘플의 경우 'GridDD')  다음과 같이 DropTarget 인스턴스를 생성해주면 된다.

 

var drop = new Ext.dd.DropTarget(Drop될 컨테이너 Element, {
      //옵션..

      ddGroup : 'GridDD', // 그리드 설정옵션의 ddGroup의 값과 동일.
      notifyDrop : function(dd, e, data){
            // to do

      }        
});

 

그리드끼리나 폼 등에서는 위와 같이 하면 작동이 되는걸 확인할 수 있는데

그리드에서 트리로 Drag&Drop을 하고자 하는 경우에는 DropTarget을 어떻게 설정을 해야 할까?

(한마디로 위와같은 방법으로는 핸들링되지 않는다.)

 

사실 tree에서는 DD가 이미 built-in 되어 있기 때문에 별도의  DropTarget 인스턴스를 생성시킬 필요가 없을 뿐더러

위와 같은 방법으로는 핸들링되지 않는다.

 

단지 tree 설정옵션인 enableDrop을 true로 바꿔주고

dropConfig만 만들어 주면 된다.설정옵션은 동일..

 

예를 들어보면 tree 설정옵션에 다음과 같이 추가하면 된다.

  enableDrop:true,
  dropConfig:{
         ddGroup : 'GridDD'
         ,onNodeDrop : function(n,dd, e, data){
               var selectedRecord = dd.dragData.selections[0]; //drag된 record
              .... 
       } 
},

 

 

 

폼패널에서는 Config 옵션에에 keys 라는 옵션이 있다.

이것은 폼패널내에서 키이벤트를 핸들링 하는 옵션이다.

많이 사용하는 예는 엔터키를 쳤을 때 OK 버튼 클릭 이벤트가 수행되도록 하는 것이며

그 예는 다음과 같다.

keys:[{
     key:[10,13] // enter
    ,scope:this
    ,stopEvent:true
    ,fn:this.onOK
   }]

TextField만를 사용할 때는  키이벤트를 어떻게 할까?

TextField에는 keydown, keypress, keyup 이라는 세가지 키이벤트를 정의하고 있음에도 불구하고

다음과 같이 리스너로 등록해봐도 작동이 되지 않는다.

listeners:{
   keydown:function(t,e){
      if(e.keyCode == 13){
        //to do
      }
  }}

왤까? 그 이유는?

This event only fires if enableKeyEvents is set to true.

 TextField에서는  enableKeyEvents 옵션이  true  인 경우에만 키이벤트를 핸들링 할 수 있다.

var field = new Ext.form.TextField({
   enableKeyEvents: true
});
field.on('keydown', function() {
   //to do
});

 

 
 
블로그 이미지

시반

시반(詩伴)이란 함께 시를 짓는 벗이란 뜻을 가지고 있습니다. 함께 나눌수 있는 그런 공간이길 바라며...

카테고리

분류 전체보기 (233)
개발 이야기 (73)
WEB2.0 (57)
ExtJS (16)
ajax (22)
DB2 (24)
MySQL (6)
오라클 (26)
기타 (44)
취미 (0)
잡담 (2)