태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

티스토리 툴바


달력

01

« 2012/01 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  
  •  
2011/02/14 16:24

ExtJS Component Life Cycle 프로그래밍/Sencha2011/02/14 16:24

Component Life Cycle

In general, the Component architecture in 2.0 will "just work." It's been designed to handle most of the management of components transparently to the end developer. However, there will come a time when something needs to be customized, or a Component needs to be extended. That's when a thorough understanding of the Component life cycle will become quite helpful. Following are the most important stages in the life cycle of every class based on Component:

Initialization
  1. The config object is applied
    Classes that extend Component do not need to (and usually should not) provide a separate constructor. Component's constructor will not only apply any config passed into its subclasses, it also provides all of the following steps.
  2. The base Component events are created
    These are events that can be fired by any Component, and they are enable, disable, beforeshow, show, beforehide, hide, beforerender, render, beforedestroy, destroy (see the Component API docs for complete details).
  3. The component is registered in ComponentMgr
    As such it will always be available via Ext.getCmp.
  4. The initComponent method is called
    This is the most important initialization step for subclasses, as this is a template method intended to be implemented by each subclass to provide any needed constructor logic. The class being created is called first, and each class in the hierarchy back up to Component is expected to call superclass.initComponent. This method makes it easy to implement and, if needed, override the constructor logic at any step in the hierarchy.
  5. Plugins are loaded (if applicable)
    If this Component has any plugins specified in the config, they will be initialized at this time.
  6. State is initialized (if applicable)
    If the Component is state-aware, its state will be reloaded if available.
  7. The component is rendered (if applicable)
    The component is rendered immediately if either renderTo or applyTo is provided in the config, otherwise rendering is deferred until the Component is explicitly displayed in code or is told to render by its container.
Rendering
  1. The beforerender event is fired
    This is a cancelable event, giving any handler the ability to prevent the Component from rendering if needed.
  2. The container is set
    If no container is specified, the parent node of the Component's underlying DOM element is set as the container.
  3. The onRender method is called
    This is the most important rendering step for subclasses, as this is a template method intended to be implemented by each subclass to provide the needed rendering logic. The class being created is called first, and each class in the hierarchy back up to Component is expected to call superclass.onRender. This method makes it easy to implement and, if needed, override the rendering logic at any step in the hierarchy.
  4. The Component is "unhidden"
    By default, many components are hidden using special CSS classes like "x-hidden". If the autoShow config value is true, any "hide" classes are removed from the component at this time.
  5. Custom class and/or style applied
    All Component subclasses support the special config properties of cls and style which are a custom, user-defined CSS class and rule respectively that will be applied to the DOM element underlying this Component. Specifying the cls value is the preferred method for visually customizing a Component and its constituent parts. Since the class will get applied to the topmost wrapper element of the Component's markup, any sub-elements of the Component can be adjusted using standard CSS inheritance rules.
  6. The render event is fired
    This is a notification that the Component has been successfully rendered at this point. You can safely assume that its DOM elements are now available to your code if needed. If you attempt to access a Component prior to rendering, it won't be available and you'll get an error.
  7. The afterRender method is called
    This is another template method for subclasses that can be implemented or overridden to provide any special post-rendering logic that may be needed. Each subclass is expected to call superclass.afterRender.
  8. The Component is hidden and/or disabled (if applicable)
    The hidden and disabled config values are applied at this point.
  9. Any state-specific events are initialized (if applicable)
    State-aware Components can declare special events that are specific to loading and saving state. If supplied, any such events will be added.
Destruction
  1. The beforedestroy event is fired
    This is a cancelable event, giving any handler the ability to prevent the Component from being destroyed if needed.
  2. The beforeDestroy method is called
    This is another template method that can be implemented or overridden to provide any special pre-destruction logic that may be needed. Each subclass is expected to call superclass.beforeDestroy.
  3. Element and its listeners are removed
    If the Component has been rendered, its underlying Element's event listeners are removed and the Element itself is then removed from the DOM.
  4. The onDestroy method is called
    This is another template method that can be implemented or overridden to provide any special post-destruction logic that may be needed. Each subclass is expected to call superclass.onDestroy. Note that the Container class (and any Container subclasses) provides a default implementation of onDestroy that automatically loops through its items collection and calls destroy on each child Component recursively.
  5. Component is unregistered from ComponentMgr
    It will no longer be available via Ext.getCmp.
  6. The destroy event is fired
    This is simply a notification that the Component has been successfully destroyed at this point and is no longer available in the DOM.
  7. Event listeners on the Component are removed
    The Component itself can have event listeners separately from its underlying Element. If any exist, they are removed.

크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > Sencha' 카테고리의 다른 글

ExtJS Component Life Cycle  (0) 2011/02/14
Ext 클래스 확장 예제  (0) 2011/02/12
ExtJS 상속  (0) 2011/02/12
Posted by 블루사랑
2011/02/12 15:17

Ext 클래스 확장 예제 프로그래밍/Sencha2011/02/12 15:17


출처 : http://www.sencha.com/learn/Tutorial:Extending_Ext_Class_(Korean)

목표

Intended resulting IconCombo

텍스트 앞에 아이콘을 보여주는 Ext.form.Combobox 확장 클래스를 만들어봅시다. 예를 들자면, 이런 콤보박스는 국가 선택을 할 때 나라 이름 앞에 국기를 보여주는 경우에 유용할 겁니다.

우리 확장 클래스에게 Ext.ux.IconCombo라는 이름을 지어줍시다.

파일 만들기

첫번째 단계는 개발 과정에 필요할 파일을 준비하는 겁니다. 아마 이런 파일들을 필요로 할겁니다.

  • iconcombo.html: 우리의 새로운 확장 클래스를 이용할 어플리케이션을 위한 HTML 파일
  • iconcombo.js: 어플리케이션의 자바스크립트 코드
  • Ext.ux.IconCombo.js: 확장 클래스의 자바스크립트 파일
  • Ext.ux.IconCombo.css: 확장 클래스의 스타일시트

iconcombo.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="../extjs/resources/css/ext-all.css">
    <link rel="stylesheet" type="text/css" href="Ext.ux.IconCombo.css">
    <script type="text/javascript" src="../extjs/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../extjs/ext-all-debug.js"></script>
    <script type="text/javascript" src="Ext.ux.IconCombo.js"></script>
    <script type="text/javascript" src="iconcombo.js"></script>
    <!-- A Localization Script File comes here -->
    <script type="text/javascript">Ext.onReady(iconcombo.init, iconcombo);</script>
    <title>Ext.ux.IconCombo Tutorial</title>
</head>
<body>
<div style="position:relative;width:300px;top:24px;left:64px;font-size:11px">
    <div>Icon combo:</div>
    <div id="combo-ct"></div>
</div>
</body>
</html>

이 HTML은 Application Layout for Beginners 튜토리얼에서 소개된 부분에서 가져와서 조금 수정했습니다.

iconcombo.js

/**
  * Ext.ux.IconCombo Tutorial
  * by Jozef Sakalos, aka Saki
  * http://extjs.com/learn/Tutorial:Extending_Ext_Class
  */
 
// reference local blank image
Ext.BLANK_IMAGE_URL = '../extjs/resources/images/default/s.gif';
 
// create application
iconcombo = function() {
 
    // public space
    return {
        // public properties, e.g. strings to translate
 
        // public methods
        init: function() {
            var icnCombo = new Ext.ux.IconCombo({
                store: new Ext.data.SimpleStore({
                    fields: ['countryCode', 'countryName', 'countryFlag'],
                    data: [
                        ['US', 'United States', 'x-flag-us'],
                        ['DE', 'Germany', 'x-flag-de'],
                        ['FR', 'France', 'x-flag-fr']
                    ]
                }),
                valueField: 'countryCode',
                displayField: 'countryName',
                iconClsField: 'countryFlag',
                triggerAction: 'all',
                mode: 'local',
                width: 160
            });
            icnCombo.render('combo-ct');
            icnCombo.setValue('DE');
        }
    };
}(); // end of app
 
// end of file

이 파일에서는 갖고 놀면서 우리의 확장 클래스를 테스트하기 위한 하나의 IconCombo 클래스를 하나 생성했습니다.

Ext.ux.IconCombo.js

// Create user extensions namespace (Ext.ux)
Ext.namespace('Ext.ux');
 
/**
  * Ext.ux.IconCombo Extension Class
  *
  * @author Jozef Sakalos, aka Saki
  * @version 1.0
  *
  * @class Ext.ux.IconCombo
  * @extends Ext.form.ComboBox
  * @constructor
  * @param {Object} config Configuration options
  */
Ext.ux.IconCombo = function(config) {
 
    // call parent constructor
    Ext.ux.IconCombo.superclass.constructor.call(this, config);
 
}; // end of Ext.ux.IconCombo constructor
 
// extend
Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {
 
}); // end of extend
 
// end of file

이 파일에서 우리가 한 것이라고는 단지 Ext.form.ComboBox의 기능만을 갖고 있는 껍데기 확장 클래스를 만든 것 뿐입니다. 하지만, 지금 단계에서는 단지 작업할 수 있는 시작점을 필요로 하기에 이걸로 충분합니다.

Ext.ux.IconCombo.css

.x-flag-us {
    background-image: url(../img/flags/us.png) !important;
}
.x-flag-de {
    background-image: url(../img/flags/de.png) !important;
}
.x-flag-fr {
    background-image: url(../img/flags/fr.png) !important;
}

여러분의 경로는 국기 아이콘들을 어디에 저장했는지에 따라 다를겁니다. 국기 아이콘들은 famfamfam.com에서 다운로드 받으시면 됩니다.

시작해볼까요?

현재까지 아주 좋습니다. 인터넷 브라우져로 iconcombo.html을 열어보면, 여러분은 아마 한개의 일반적인 콤보박스를 보게 될 겁니다. 이 콤보박스는 세개의 아이템을 갖고 있고 독일이 선택되어 있을겁니다. 맞지요? 물론, 아직 아이콘은 없지요...

자 이제 작업을 시작해볼까요. 다음 코드를 Ext.ux.IconCombo.js 파일에 추가하시는데, 부모 생성자 호출부분 바로 다음에 추가하세요.

this.tpl = config.tpl ||
      '<tpl for="."><div class="x-combo-list-item">'
    + '<table><tbody><tr>'
    + '<td>'
    + '<div class="{' + this.iconClsField + '} x-icon-combo-icon"></div></td>'
    + '<td>{' + this.displayField + '}</td>'
    + '</tr></tbody></table>'
    + '</div></tpl>'
;

여기서는 기본 콤보박스 아이템 템플릿을 iconClsField를 이용하는 우리의 템플릿으로 오버라이드 했습니다.

이제는 다음 내용을 Ext.ux.IconCombo.css 파일에 추가하세요.

.x-icon-combo-icon {
    background-repeat: no-repeat;
    background-position: 0 50%;
    width: 18px;
    height: 14px;
}

좋군요. 다음 테스트를 위한 준비가 되었으니 브라우져에 있는 페이지를 다시 불러보시죠. 멋지지 않습니까?

리스트가 펼쳐졌을 때 멋진 아이콘들을 갖게 되었는데, 이게 접혔을 때도 국기가 보이게 하고 싶군요. 여러분도 그렇지요?

그럼 다음 코드를 생성자에 있는 템플릿 생성 부분 뒤에 넣어보세요.

this.on({
    render:{scope:this, fn:function() {
        var wrap = this.el.up('div.x-form-field-wrap');
        this.wrap.applyStyles({position:'relative'});
        this.el.addClass('x-icon-combo-input');
        this.flag = Ext.DomHelper.append(wrap, {
            tag: 'div', style:'position:absolute'
        });
    }}
});

이 코드는 render 이벤트 리스너를 추가하는 겁니다. 이 리스너는 엘리멘트들에 스타일을 적용하고 국기를 위한 div 콘테이너를 추가합니다.

그리고, 다음 내용을 extend 부분에 추가합니다. 그럼 이렇게 되겠지요.

// extend
Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {
 
    setIconCls: function() {
        var rec = this.store.query(this.valueField, this.getValue()).itemAt(0);
        if(rec) {
            this.flag.className = 'x-icon-combo-icon ' + rec.get(this.iconClsField);
        }
    },
 
    setValue: function(value) {
        Ext.ux.IconCombo.superclass.setValue.call(this, value);
        this.setIconCls();
    }
 
}); // end of extend

우리는 setIconCls 함수를 추가하고 setValue 함수를 오버라이드했습니다. 당연히, 우리는 원래의 setValue 함수가 제 역할을 하기를 원하기 때문에, 먼저 부모의 setValue 함수를 호출하고 나서 우리가 만든 setIconCls 함수를 호출합니다.

다음 내용을 여러분의 Ext.ux.IconCombo.css 파일에 추가하세요.

.x-icon-combo-input {
    padding-left: 26px;
}
.x-form-field-wrap .x-icon-combo-icon {
    top: 3px;
    left: 6px;
}

드디어 마지막

자 이제 마지막 테스트입니다. HTML 페이지를 다시 불러보세요. 갖다 붙이는 데 실수만 하지 않았다면, 여러분은 이제 자신만의 새로운 Ext.ux.IconCombo 확장 클래스를 갖게 된 겁니다. 여러분이 여기까지 한 내용은 Ext 클래스를 확장하는 가장 기본적인 것들이었고, 여러분은 더 개선할 수 있을 것입니다.

Brian Moeskau 덕분에, 저는 Ext.ux.IconCombo를 간소화시켰고, 이제는 여러분의 어플리케이션에 사용될 수 있을 정도의 최종 버전이 되었다고 생각됩니다. 그 자바스크립트 코드와 css는 다음과 같습니다.

Ext.ux.IconCombo.js

// Create user extensions namespace (Ext.ux)
Ext.namespace('Ext.ux');
 
/**
  * Ext.ux.IconCombo Extension Class
  *
  * @author  Jozef Sakalos
  * @version 1.0
  *
  * @class Ext.ux.IconCombo
  * @extends Ext.form.ComboBox
  * @constructor
  * @param {Object} config Configuration options
  */
Ext.ux.IconCombo = function(config) {
 
    // call parent constructor
    Ext.ux.IconCombo.superclass.constructor.call(this, config);
 
    this.tpl = config.tpl ||
          '<div class="x-combo-list-item x-icon-combo-item {' 
        + this.iconClsField 
        + '}">{' 
        + this.displayField 
        + '}</div>'
    ;
 
    this.on({
        render:{scope:this, fn:function() {
            var wrap = this.el.up('div.x-form-field-wrap');
            this.wrap.applyStyles({position:'relative'});
            this.el.addClass('x-icon-combo-input');
            this.flag = Ext.DomHelper.append(wrap, {
                tag: 'div', style:'position:absolute'
            });
        }}
    });
} // end of Ext.ux.IconCombo constructor
 
// extend
Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, {
 
    setIconCls: function() {
        var rec = this.store.query(this.valueField, this.getValue()).itemAt(0);
        if(rec) {
            this.flag.className = 'x-icon-combo-icon ' + rec.get(this.iconClsField);
        }
    },
 
    setValue: function(value) {
        Ext.ux.IconCombo.superclass.setValue.call(this, value);
        this.setIconCls();
    }
 
}); // end of extend
 
// end of file

Ext.ux.IconCombo.css

/* application specific styles */
.x-flag-us {
    background-image:url(../img/flags/us.png) !important;
}
.x-flag-de {
    background-image:url(../img/flags/de.png) !important;
}
.x-flag-fr {
    background-image:url(../img/flags/fr.png) !important;
}
 
/* Ext.ux.IconCombo mandatory styles */
.x-icon-combo-icon {
    background-repeat: no-repeat;
    background-position: 0 50%;
    width: 18px;
    height: 14px;
}
.x-icon-combo-input {
    padding-left: 25px;
}
.x-form-field-wrap .x-icon-combo-icon {
    top: 3px;
    left: 5px;
}
.x-icon-combo-item {
    background-repeat: no-repeat !important;
    background-position: 3px 50% !important;
    padding-left: 24px;
}
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > Sencha' 카테고리의 다른 글

ExtJS Component Life Cycle  (0) 2011/02/14
Ext 클래스 확장 예제  (0) 2011/02/12
ExtJS 상속  (0) 2011/02/12
Posted by 블루사랑