자바스크립트/Ext JS2013. 10. 13. 15:08

ExtJS 4 클래스 시스템


ExtJS는 300여개 이상의 클래스와 이를 기반한 아키텍쳐를 가졌다. 객체지향 언어를 표방해 상속, 다중상속, 이벤트를 통한 접근 등 고급언어에서 볼 수 있는 거의 모든 개념을 탑재해 다양하고 복잡한 어플리케이션 구현이 가능하다.


자바스크립트는 유연한 언어다. 그러나 이러한 유연함이 많은 코딩스타일과 기법 등을 낳게 됐고 코드를 예측하거나 유지하는 데 많은 비용을 지불하게 됐다. ExtJS 클래스 시스템은 캡슐화를 지원하고, 표준코딩 컨벤션을 사용 할 수 있어 작성된 코드의 예측, 확장이 용이하다. ExtJs 클래스시스템을 통해 시간이 지날 수록 어플리케이션의 가치는 증가하고 안정적인 유지보수가 가능해 진다.

 

이장에서는 아래 기능을 통해 ExtJs의 새로운 클래스시스템을 맛보고 배우게 된다. ExtJS를 이해하는 가장 기초적이며 가장 중요한 장이라 하겠다.

  • 클래스 선언과 생성
  • Config 기반 구성요소
  • 상속(클래스 확장)
  • 믹스인(Mixins)
  • 스태틱
  • 동적 클래스 로딩
  • Alias(xtype)

클래스 선언과 생성

아래 코드는 전형적인 ExtJS 클래스 정의 및 생성 방법이다.

Ext.define('MyClass', {         // Step 1

    extend : 'Ext.panel.Panel',     // Step 2

    title : '안녕하세요 환영합니다.^^',

    initComponent : function() {     // Step 3

        var me = this;

        this.callParent(arguments);    // Step 4

    }

});

 

var myClass = Ext.create('MyClass', {     // Step 5

    renderTo : Ext.getBody()

});

 

Step1 : Ext.define함수를 통해 클래스를 정의했다. 클래스명에는 문자와 숫자가 포함될 수 있고 밑줄은 권장하지 않는다. 패키지를 표현하기 위해 '.'으로 구분하며 아래 예시처럼 최상위이름과 최종이름은 카멜케이스를 쓰고 그 외에는 소문자로 표현하는 것을 권장한다.


    MyClass.form.action.AutoLoad

 

Step2 : 상속받아 확장하려는 클래스를 명시한다. ExtJS는 300여개 이상의 클래스가 존재하고 이중 하나를 골라 적절히 수정해 원하는 기능을 구현한다.

    

Step3 : 확장할 클래스 기능을 재정의 할 때 initComponent함수가 사용된다.

이 함수는 확장할 클래스 구성요소를 초기화하고 원하는 대로 변경 할 수 있게한다.

 

Step4 : "this.callParent(arguments)"는 확장할 클래스의 initComponent함수를 호출한다. 이는 재정의한 내용을 확장할 클래스에 전달해서 확장할 클래스가 작동하기 위함이다.

 

Step5 : 정의된 클래스를 사용하기 위한 클래스 생성코드다. ExtJs는 정의된 클래스를 생성시 Ext.create함수를 사용해 생성하고 위 코드처럼 특정 변수에 인스턴스를 저장한다.

 

아래 그림은 위의 코드를 실행한 결과다.

Config 기반 구성요소

ExtJS 클래스 시스템은 config설정 기능을 제공한다. 클래스에 config옵션을 정의하면 클래스 시스템은 자동으로 4개 메소드(getter, setter, reset, apply)를 생성한다. 이를 통해 클래스에 매개변수를 전달해 값을 설정하고 수정할 수 있으며 코드라인이 줄어들어 API간 일관성을 유지할 수 있는 장점을 제공한다.

 

새로운 클래스를 만들고 config를 설정 해보자.

Ext.define('Benney.ClassRoom', {

    config : {                // Step1

        grade : '미정',

        className : '미정',

        teacher : '미정'

    },

    constructor : function(config) {    

        this.initConfig(config);    // Step2

    },

    getString: function(){    // Step3

        return     '- 교실정보 -\n학년 : '

                + this.getGrade()

                + '\n반명 : ' + this.getClassName()

                + '\n담임 : ' + this.getTeacher();

    }

},

function() {

    console.log('Benney.ClassRoom class가 정의됐음!');

});

 

var classroom = Ext.create('Benney.ClassRoom');    // Step4

classroom.setGrade('2');                // Step5

classroom.setClassName('꾸러기')

classroom.setTeacher('홍길동');

console.log(classroom.getString());            // Step6


아래 그림은 위의 코드를 실행한 결과다.

Step1 : config정보를 정의한다. 위의 코드에서는 grade, className, teacher 등 3개 config변수를 선언했다.

 

Step2 : 생성자 함수로 여기서는 'this.initConfig(config)'함수를 호출해 config변수를 초기화 했다. 예제는 기존 ExtJS클래스를 확장하지 않아 생성자에 'this.initConfig(config)'를 호출하지만 확장하면 initComponent함수 내부에서 실행되게 코딩 해야한다.

 

Step3 : getString()함수는 config로 설정된 내부 변수값을 확인하기 위해 각 config 변수의 getter메소드를 호출한다.

 

Step4 : 정의한 클래스를 생성한다.

Step5 : 외부에서 새로운 값을 세팅한다.

Step6 : 새로 세팅된 값이 적용됐는지 getString메소드를 통해 확인한다.

 

위에서 getter, setter메소드를 알아봤다. 이제 소스를 수정해 apply메소드를 알아보자.

apply메소드는 setter메소드 호출 시 자동으로 실행된다..

아래 코드는 setter메소드 이후에 apply메소드가 호출되는지 알아보기 위해 각config변수에 맞는 apply메소드를 재정의 하였다. 기존 getString메소드의 텍스트 문구는 각 apply메소드로 이전했다.

    applyGrade : function(grade){

        this.grade = '학년 : ' + grade

    },

    

    applyClassName : function(className){

        this.className = '반명 : '+ className;

    },

    

    applyTeacher : function(teacher){

        this.teacher = '담임 : '+ teacher;

    },

    getString: function(){    // Step3

        return     '- 교실정보 -\n'

                + this.getGrade()

                + '\n' + this.getClassName()

                + '\n' + this.getTeacher();

    }


위의 코드를 실행하면 이전과 동일한 내용의 결과가 확인된다. 이처럼 apply메소드는 setter메소드와는 달리 config값을 포함한 그 밖의 내용을 설정하기 위해 사용한다.

  

상속(클래스 확장)

ExtJS는 extend함수를 통해 상속을 지원한다. 상속을 통해 이미 존재하는 클래스 기능을 그대로 사용하면서 원하는 기능만 일부 수정한다. 상속을 통해 UI가 존재한다면 UI를, 기능이 존재한다면 함수를 재활용 한다.

아래 코드는 'ClassRoom'클래스를 정의하고 이를 확장해 'Student'클래스를 만든다.


  •  ‘RiaApp.ClassRoom’이라는 이름의 클래스를 정의한다.

Ext.define('RiaApp.ClassRoom', {

    config : {

        grade : '미정',

        className : '미정',

        teacher : '미정'

    }

});


  • config정보를 재정의할 apply메소드를 정의한다.

applyGrade : function(grade) {

this.grade = '학년 : ' + grade

},

      applyClassName : function(className) {

this.className = '반명 : ' + className;

},

applyTeacher : function(teacher) {

this.teacher = '담임 : ' + teacher;

},


  • 생성자를 정의하고 config정보를 초기화 한다.

constructor : function(grade, className, teacher) {

this.initConfig(); // 초기화 실행

if (grade) // setter메소드로 인자로 받아온 값을 세팅한다.

this.setGrade(grade);

if (className)

this.setClassName(className);

if (teacher)

this.setTeacher(teacher);

},


  • 전체 config정보를 출력 할 메소드를 정의한다.

getString : function() {

  console.log('RiaApp.ClassRoom called')

        return '\n- 교실정보 -\n' + this.getGrade() + '\n' +  this.getClassName()

                + '\n' + this.getTeacher();

}


  • 클래스를 실행할 코드를 만든다. 클래스명 뒤에 학년, 교실명, 담임명을 인자로 전달하면 생성자에 의해 
    config정보가 세팅된다.

var classroom = Ext.create('RiaApp.ClassRoom', '2', 'ExtJS배워보기', '홍길동');

console.log(classroom.getString());

    

  • 프로그램을 실행하고 콘솔을 통해 확인한다.

  • ClassRoom클래스를 확장해 Student클래스를 만들어 보자. 이 Student클래스는 studentName,
    studentAddress라는 두개 config변수를 가진다.

Ext.define('RiaApp.Student',{

extend : 'RiaApp.ClassRoom',    // 확장클래스명

      config : {                // config

          studentName : '',

          studentAddress : ''

}

});


  • 생성자를 구현한다. 생성자는 외부로부터 인자를 받아 현클래스 config정보를 세팅하고 확장한 클래스 
    생성자도 호출해 config정보를 세팅했다.

constructor : function(grade, className, teacher,

      studentName, studentAddress) {    // Step1

            

          this.initConfig();    // Step2

          if (studentName)     // Step3

              this.setStudentName(studentName);

          if (studentAddress)

              this.setStudentAddress(studentAddress);

            

          // Step4

          this.callParent([ grade, className, teacher ]);

},

Step1 : 클래스 생성시 외부에서 받아올 인자로 확장할 클래스에서 사용할 인자도 포함한다.


Step2 : config정보 초기화를 위해 this.initConfig()를 호출한다.


Step3 : 인자로 받아온 값이 정상적이라면 setter메소드를 통해 config를 설정한다.


Step4 : this.callParent함수는 확장한 슈퍼클래스의 함수를 호출 한다. 이 코드를 호출한 함수와 동일한 이름의 함수를 슈퍼클래스에서 호출한다. 여기서는 생성자에서 호출돼 슈퍼클래스 생성자를 호출한다. this.callParent호출 시 3개(grade, className, teacher) 인자를 넘긴다. 슈퍼클래스 생성자 또한 이 3개 인자를 받아 구현됐다.


  • getStudent함수는 getString()함수와 함께 학생정보와 교실정보를 한꺼번에 표시한다..

getStudent : function(){

    return '- 학생정보 -'

    + '\n이름 : '+ this.getStudentName()

    + '\n주소 : '+ this.getStudentAddress() +

    this.getString();

},


  • getString()함수를 보자. 아래 코드는 return this.callParent()만 존재한다. 이는 슈퍼클래스 getString()함수를 호출하고 그 값을 반환하라는 의미다.

getString : function() {

    console.log('RiaApp.Student called')

    return this.callParent();

}


  • 여기까지 ClassRoom클래스를 확장해 Student클래스를 작성했다. 작성된 클래스를 생성하고 getStudent()함수를 호출한다.

var student = Ext.create('RiaApp.Student','2','꾸러기', '홍길동','김철수', '경기도 고양시 일산동');

console.log(student.getStudent());


  • 아래 그림은 위의 코드를 실행한 결과다.

클래스 확장은 가장 강력한 기능이고 모든 클래스에서 광범위하게 사용된다. 위에서는 쉽게 설명하기 위해 UI가 없는 클래스를 작성했지만 대부분 UI콤포넌트를 확장해 프로그래밍을 한다.

 

믹스인(Mixins)

ExtJs는 단일 클래스만 상속할 수 있어 다중 상속을 지원하기 위해 믹스인(Mixins)을 사용한다. 여러개 클래스를 믹스인을 통해 참조하고 참조된 클래스 기능을 사용할 수 있게 했다. 상속(extend)과 override와 유사하지만 이미 존재하는 함수를 교체하지 않는다.

앞서 설명한 'ClassRoom'클래스를 Mixins에 포함시키고 Ext.panel.Panel클래스를 확장해 UI를 갖는 변형된 Student클래스를 만든다. 대부분 경우 UI 클래스로 이와 함께 config를 포함하면서 Mixins를 같이 사용하는 경우를 위한 예제다.


  • Ext.define을 사용 클래스를 정의한다. 이전 'Student'클래스와 달리 Ex.panel.Panel클래스를 상속받고 mixins내부에 classroom변수에 'RiaApp.ClassRoom'클래스를 문자열로 참조했다.

Ext.define('RiaApp.Student',{

    extend : 'Ext.panel.Panel',

        config : {

            studentName : '',

            studentAddress : ''

        },

        mixins : {

            classroom : 'RiaApp.ClassRoom'

        },


  • initComponent는 컴포넌트 초기화를 위한 함수다. 아래처럼 코드구현이 끝나면 this.callParent()를 실행, 상속한 클래스의 initComponent함수를 호출하고 동일한 초기화를 진행한다. this.mixins.classroom.constructor은 mixins에 설정된 변수에 접근하기 위한 코드다. 'ClassRoom'클래스에 접근해 생성자를 호출하고 3개 인자를 전달한다.

      initComponent: function(){

          // mixins의 classroom변수에 접근 생성자 호출

          this.mixins.classroom.constructor

              (this.grade, this.className, this.teacher );

      

          this.callParent(arguments);

},


  • 학생정보를 출력하는 함수다. Mixins을 참조해 'ClassRoom'클래스 getString()함수를 호출한다.

getStudent : function(){

            return '- 학생정보 -'

            + '\n이름 : '+ this.getStudentName()

            + '\n주소 : '+ this.getStudentAddress() +

            this.mixins.classroom.getString();

      }


  • 실행코드를 작성한다. 이 클래스는 Ext.panel.Panel클래스를 상속받아 이전과 달리 config정보를 인자로 전달하지 않고 아래처럼 '{}'내부에 Panel에서 사용하는 기타 정보와 같이 전달했다.

    var student = Ext.create('RiaApp.Student',{

        title : 'Hello Student !!',

        html : '안녕하세요 여러분',

        grade : '2',

        className : '꾸러기',

        teacher : '홍길동',

        studentName : '김철수',

        studentAddress : '경기도 고양시 일산',

        renderTo : document.body

    });

 

  • 위의 코드를 실행하면 아래처럼 이전과 동일한 내용이지만 Ext.panel.Panel클래스로 인해 UI가 존재하는 클래스가 됐다.

 

스태틱

모든 클래스는 스태틱(statics)메소드를 정의할 수 있다. static은 인스턴스를 생성하지 않고 접근이 가능하다. 즉 create로 생성하지 않고 '클래스명.변수/함수'로 접근한다.

아래 코드를 살펴보자. (좀더 보강…)

Ext.define('Student', {

config : {

          studentName : null

      },

statics : {


studentCount : 0,

            student : function(studentName) {

                return new this({    // 강제로 생성자 호출

                    studentName : studentName

                });

}

},

      // 생성자

constructor : function(config) {

this.initConfig(config);

     // this.statics().studentCount++;과 동일

this.self.studentCount++;

return this;

}

});

var student1 = Student.student('홍길동');

var student2 = Student.student('김철수');

console.log(student2.getStudentName());

console.log(Student.studentCount);

 

아래 그림은 위의 코드를 실행한 결과다.

동적클래스 로딩

동적 클래스 로딩은 ExtJS4의 새로운 기능으로 빠른 페이지 로딩보다는 유연성이 중요한 개발환경에서 사용된다. 자바스크립트를 사용하기 위해 HTML파일 내부에 아래처럼 자바스크립트 파일을 포함시켜야 한다.

<script type="text/javascript" src="app.js"></script>

운영환경은 모든 자바스크립트 파일을 병합, 압축해 HTML파일에 포함시키지만 개발환경에서는 병합, 압축하지 않은 독립된 파일로 존재하는 클래스를 HTML파일에 포함시켜야 하는 경우가 발생한다. 즉 Student클래스가 ClassRoom클래스를 상속했다면 절대로 ClassRoom클래스 파일이 HTML 파일에 포함돼 있어야 한다.

 

  • 예제를 통해 확인해 보자. 아래 그림은 예제 폴더구조다. 앞서 살펴본 ClassRoom, Student클래스를 활용 동적 클래스로딩이 어떻게 작동되는지 알아보자.

 

 

예제 루트에 src폴더를 만든다. 일반적인 형식이니 따르기로 하자. src폴더 밑에 우리가 만들 어플리케이션 이름으로 폴더를 하나 더 생성한다. 이전 믹스인과 상속을 설명한 예제에서 ClassRoom, Student 두개 코드만 추출해 각기 클래스명으로 js파일을 생성했다.

 

  • inxdex.html파일을 작성하자. 두 개 define된 클래스와 이를 생성하고 실행시키는 app.js 등 총3개 js파일을 포함시켰다.

 

ClassRoom 클래스와 Student클래스는 앞서 설명한 내용과 동일하다. 단 이 2개 클래스를 생성하여 실행하는 방법을 설명하려 한다.

아래 코드는 동적로딩을 사용하지 않고 html파일에 필요한 js파일들이 포함돼 있어 정상적으로 실행된다.

// 이하 app.js

Ext.onReady(function() {

    

    var student = Ext.create('RiaApp.Student',{

        title : 'Hello Student !!',

        html : '안녕하세요 여러분',

        grade : '2',

        className : '꾸러기',

        teacher : '홍길동',

        studentName : '김철수',

        studentAddress : '경기도 고양시 일산',

        renderTo : document.body

    });

    console.log(student.getStudent()); // Step6

});

 

  • 아래 그림은 위의 코드를 실행한 결과다.

  • 이제 동적클래스 로딩을 테스트 하기 위해 index.html파일 내부 ClassRoom.js와 Student.js파일을 주석 처리하고 app.js내 Ext.onReady전에 아래처럼 Ext.Loader를 설정한다.

// Configure the Ext.Loader class

Ext.Loader.setConfig({

    enabled : true,     // Step1

    paths : {        // Step2

        'RiaApp' : 'src/RiaApp'

    }

});

Ext.require('RiaApp.Student'); // Step3

Ext.onReady(function() {

..

 

Step1 : Ext.Loader를 사용할 수 있게 활성화 한다.

Step2 : src폴더를 RiaApp라는 이름으로 경로를 잡아준다. src폴더에는 'RiaApp.'으로 시작하는 클래스가 위치한다.

Step3 : Ext.require함수에 동적로딩 할 클래스를 명시한다.

 

  • 브라우저를 통해 실행한다. 이전과 동일하게 실행된다. Index.html파일 내부에 두 개 클래스 파일이 주석으로 제거된 상태에도 이전과 같이 정상적인 결과를 보여준다. 위의 코드로 인해 내부적으로 어떤 일이 생겼는지 확인해 보자. 아래 그림은 인스펙터 Element탭에서 최종 실행 된 html 결과다. 

그림을 자세히 보면 ClassRoom.js와 Student.js는 주석처리 됐고 app.js하단에 다시 ClassRoom.js와 Student.js가 링크된 것이 보인다. 왜 일까? 주석으로 막힌 두개의 js파일은 앞서 우리가 주석 처리한 코드이고 app.js하단 두개의 js파일은 Ext.Loader 설정에 의해 자동으로 생성됐다. 즉 Ext.Loader를 설정하고 Ext.require('RiaApp.Student')를 통해 동적로딩할 클래스를 명시했기 때문에 자동으로 Student.js파일 링크가 생성됐다. 그런데 우리가 필요하다고 설정한 클래스는 RiaApp.Student클래스 하나로 ClassRoom.js은 왜 있는 것일까?

 

이는 ExtJS 클래스 시스템이 RiaApp.Student클래스를 실행하기 위해 필수적으로 필요한 클래스가 무엇인지 파악한 후 필요한 클래스도 같이 로딩하기 때문이다.

 

이처럼 동적클래스 로딩은 특정 폴더를 경로로 설정해 폴더내부 클래스 파일을 Ext.require를 통해 로딩해줘 html파일에 수작업으로 js파일을 링크하지 않는다.

이는 개발단계에서 특정 라이브러리를 포함하거나 그외 어플리케이션 클래스를 사용할 경우 유용하다.

 

  • 좀더 알아보자. 아래 처럼 Ext.require를 주석처리하고 실행한다.

//Ext.require('RiaApp.Student');

이전과 달리 콘솔창 상단에 경고메시지가 출력된다. 메시지 내용은 Ext.onReady상단에 Ext.require('RiaApp.Student')를 추가하라는 내용이다. 경고를 보였을 뿐 정상적으로 프로그램은 실행됐다. 다시 인스펙터 Element탭을 보자. 이전과 달라진 점이 무엇인지 아래 그림을 통해 확인하자.

 

이전과 달리 app.js하단에 ClassRoom.js와 Student.js 파일 링크가 없어졌다. 이는 Ext.require를 주석 처리해 링크가 사라진 것이다.

그렇다면 왜 프로그램은 정상적으로 실행됐을까?

 

  • 이유는 실행 코드에 있다. 우리는 Ext.Loader를 통해 RiaApp이하 클래스 폴더가 어디 있는지 설정해 줬다.

Ext.Loader.setConfig({

    enabled : true,

    paths : {

        'RiaApp' : 'src/RiaApp'

    }

});


  • 이후 이 예제를 실행하기 위해 Ext.create를 사용했다. 즉 아래처럼 클래스 풀네임을 쓰고 생성할 경우 이미 RiaApp클래스 폴더 경로(src/RiaApp)가 존재해 RiaApp.Student로 생성해도 Student클래스에 직접 접근 가능하다.

var student = Ext.create('RiaApp.Student',{ // src/RiaApp폴더에 접근 가능

    title : 'Hello Student !!',

    …

    renderTo : document.body

});

 

Alias (xtype)

이렇게 실행에 문제가 없다면 왜 경고를 보여주는 것일까? Ext.create는 단일 클래스를 생성하는 코드로는 적합하나 여러 개 클래스를 하나의 클래스 자식으로 포함 할 경우에는 부적합하다. 이 경우 변수를 통해서 자식을 추가하기 보다는 클래스에 alias를 설정해 부모가 될 클래스 xtype속성으로 사용하는 것을 권장한다.

 

  • Student클래스에 alias를 'widget.student'로 지정하자. 'widget.'이후 student가 위젯명으로 사용된다.

Ext.define('RiaApp.Student', {

extend : 'Ext.panel.Panel',

      alias : 'widget.student',

 

  • Ext.create를 통한 실행코드를 위의 alias로 변경해 본다. 아래 코드는 Ext.Viewport를 생성하고 Student클래스를 alias명으로 Ext.Viewport item으로 추가하는 코드다.

    // Step1

    Ext.create('Ext.Viewport',{

        items : [{

            // xtype 을 이용해 컴포넌트를 배치한다.

            // 여기서는 정확히 require가 돼 있어야 한다.

            // xtype으로는 상단경로와 함께 클래스를 찾지 못한다.

            xtype : 'student',        // Step2

            title : 'Hello Student !!',

            html : '안녕하세요 여러분',

            grade : '2',

            className : '꾸러기',

            teacher : '홍길동',

            studentName : '김철수',

            studentAddress : '경기도 고양시 일산'

        }]

    });

 

Step1 : Ext.Viewport는 브라우저에 유일하게 하나만 존재하는 최상위 객체다.

Step2 : Ext.Viewport 자식으로 추가한다. xtype속성에 Student클래스 alias명을 넣는다.

기존 Ext.create 내부 코드를 Ext.Viewport 내부 items 코드안으로 그대로 가져왔다.

 

  • 아래 그림은 위의 코드를 실행한 결과다.

실행 결과 'widget.student'를 인식하지 못한다. 이는 alias로 사용한 위젯명이 클래스명 처럼 '.'을 통해 폴더명을 포함하지 않고 'student'로 함축적으로 사용했기 때문에 widget.student인 Student클래스를 못찾는다. 이때 필요한 것이 Ext.require('RiaApp.Student') 코드다. 이전에 주석처리 했으므로 주석을 없애고 다시 실행하면 정상적으로 동작한다.

이처럼 widget형태로 간략히 쓰기 위해서는 Ext.require를 통해 필요한 클래스가 미리 로딩돼야 한다..


section2.zip


 

Posted by 베니94
자바스크립트/Ext JS2013. 9. 17. 20:13

ExtJS MVC구조를 통해 어플리케이션을 개발시 고민 중 하나가 컨트롤러의 등록이다. 

보통에 경우 app.js 즉 Ext.Application을 상속받은 클래스에 사용할 Controller를 등록하게 된다.


그러나 개발 시에는 매번 생성되는 컨트롤러를 app.js에 등록 하기 어렵고? 아니 귀찮고 규모가 큰 시스템에 경우

컨트롤러도 많아 지게 되어 모두 등록한다는 것 자체가 왠지 성능상에 좋지 않을 듯 싶다.


해서 생각한 것이 다이나믹하게 컨트롤러를 그때 그때 등록할수 있는 방법을 사용하게 된다.

대충 기술하자면 한개 정도의 미리 등록된 컨트롤러가 참조하고 있는 뷰를 통해 해당 컨트롤러에 

접근하면서 사용할 컨트롤러의 이름을 전달하고 접근과 동시에 application클래스에 특정 메소드를 호출하여

아래와 같이 새로운 컨트롤러를 등록하도록 하였다.

application안에서 컨트롤러를 등록하는 방법은 

var controller = this.getController('사용할 컨트롤러 클래스명');

controller.init(this); -> 여기서 this는 어플리케이션 클래스 이다.


문제는 이때 발생한다. 개발 모드에서 다이나믹하게 컨트롤러를 등록하여 사용할 수 있는 코드는 구축이 되었지만

실서버에 배포할 요량으로 빌드를 해보니 app.js에 등록되지 않은 컨트롤러는 빌드에서 빠지는 현상이 발생한다.


이는 ExtJS가 클래스의 종속성에 대해 검증하는 과정에서 사용되지 않는 즉 require가 없거나 참조관계 등이 없을 경우

실제 클래스 파일이 존재하는데도 빌드에서는 제외 시킨다는 것이다.


이 경우에는 Sencha Cmd로 생성한 어플리케이션 내의 build.xml파일을 수정하여 언제 사용될지 모르나 이미 존재하는 클래스를

빌드에 포함시키도록 할 수 있다.



어플리케이션 클래스
Ext.application({
    name: 'MyApp',
    appFolder: 'app',

    controllers: [
        "main.App"
    ],

    uses: [
        /*ant-generated-content-start*/ /*ant-generated-content-end*/
    ],

    autoCreateViewport: true,
});
build.xml

    

    

        
        
            
        
        
            
                
                
                    
                    
                        
                        
                    
                
            
        
        

        
        
    

    
        
        
    


참고 : http://stackoverflow.com/questions/14457508/using-sencha-cmd-with-dynamically-loaded-controllers
Posted by 베니94
자바스크립트/Ext JS2013. 7. 3. 09:37

ExtJS로 뭘하나 만들어 볼까 싶어서 몇일 만지작 거리다.


집에 안쓰고 모셔놓은 HP미니 서버를 좀 활용해 사이트를 올려 봅니다.


아직 작업하는 중이고 미완성입니다.


좀 완성도를 높여 상시적으로 Q&A게시판으로 활용하고 


소스는 강좌를 통해 공개하려고 합니다.


주소 : http://benney.able.or.kr



Posted by 베니94
자바스크립트/Ext JS2013. 6. 24. 23:40

안녕하세요 ExtJS 3번째 오프라인 강좌로 "ExtJS Class System & MVC 알아보기"를 
준비 했습니다.

ExtJS만의 클래스 시스템과 MVC 패턴을 통한 구현 방법을 알아보고 실무에 사용되는 
유용한 팁도 공유합니다. 

[강사소개]

    • 삼성SDS ExtJS 강의 수행
    • 한국센챠유저그룹 활동
    • 온오프믹스 ExtJS 강의 진행
    • ExtJS를 적용하여 다수의 시스템 구축 경험
    • Blog : http://benney.tistory.com

[세부 내역]

  • 대상 : ExtJS 초, 중급, ExtJs에 관심 있는 모든분들.
  • 일시 : 6월 29일(토) 17:00 ~ 19:00
  • 장소 : 토즈 강남 2호점(타워점 아닙니다.)
    • URL : http://www.toz.co.kr/branch/main/index.htm?id=11
  • 등록비용 : 50,000원
  • 등록하기 (http://onoffmix.com/event/16084)
  • 강의방식 : 준비 된 샘플을 통한 진행(실습아님)
  • 강의내용
    • ExtJS Class System
      1. Define & Create
      2. Config
      3. Extend & Mixins
      4. Static
      5. Dynamic Class Loading
    • ExtJS MVC의 소개
      1. MVC란 무엇인가?
      2. MVC를 통해 무엇을 얻을 수 있나?
      3. 각 요소에 대한 샘플을 보고 역할을 알 수 있다.
      4. Controller는 만능인가? 알고 쓰자 Controller


    • 기타 문의는 benneykwag@gmail.com으로 해주세요

      종료 후 뒷풀이를 하려고 합니다. 참석하신다는 분들이 있으면요 ^^
      (비용은 부담되지 않는 선에서 나누어 내도록 하시지요)


Posted by 베니94
카테고리 없음2013. 6. 14. 17:35

IOS7베타 버전이 출시되었습니다. 개인적으로 애플 제품을 상당히 선호하는 저에게

최근 애플의 행보~ 꼭 집어서 얼굴만 길어진 아이폰 5에 대한 불만이 상당합니다.


아이폰4를 사용 중이고 자연스럽게 아이폰5를 기다렸지만 실망감에 안드로이드로

전환할 까 고민하고 있습니다.


현재 아이폰 4(IOS6.1.3)의 문제는 다음과 같습니다.

1. 속도 

- 공장 초기화를 해서 좀 빨라졌지만 전반적으로 어플실행 속도등이

   버전이 올라갈수록 아이폰4에서는 점점 느려지고 있음.

- 한영전환, 페이스북, 웹브라우징

2. 화면사이즈

- 느림과 동시에 점점 얼굴을 찡그리며 처다봐야할 정도 임.

- 점점 눈의 기능이 떨어지므로 좀 더 큰 화면이 필요함.


3. 변화

- 기능적 변화가 그 동안 크지 않았고 애플은 심플하고 오래 갈수 

  있는 기능만 살린다고 생각하고 있지만 일부 편의 기능은 안드로이드에

  뒤져 있는 부분이 있음.


해서 현재 출시된 IOS7을 미리 체험해보고 아이폰5로 갈지 안드로이드로 갈지 

결정을 내리기로 했습니다.



Posted by 베니94
Tools2013. 6. 9. 19:19

아주 깔끔하고 가벼운 놈이다. ^^

기능도 상당하다.~


'Tools' 카테고리의 다른 글

Web 화면 설계 툴 - PowerMockUp  (0) 2013.02.02
Posted by 베니94
자바스크립트/Ext JS2013. 5. 25. 14:22

ExtJs 4.2 버전에서 전에 없던 툴팁 버그가 발생한다. 아래 그림과 같이 툴팁의 길이가 동적으로 늘어나지 않고 

텍스트가 일정크기 이상으로 늘어나지 않고 갇히게 된다.



이를 해결하기 위해 아래와 같이 Ext.tip.QuickTip클래스를 override한다.


Ext.override(Ext.tip.QuickTip, {
    helperElId: 'ext-quicktips-tip-helper',
    initComponent: function ()
    {
        var me = this;


        me.target = me.target || Ext.getDoc();
        me.targets = me.targets || {};
        me.callParent();


        // new stuff
        me.on('move', function ()
        {
            var offset = me.hasCls('x-tip-form-invalid') ? 35 : 12,
                helperEl = Ext.fly(me.helperElId) || Ext.fly(
                    Ext.DomHelper.createDom({
                        tag: 'div',
                        id: me.helperElId,
                        style: {
                            position: 'absolute',
                            left: '-1000px',
                            top: '-1000px',
                            'font-size': '12px',
                            'font-family': 'tahoma, arial, verdana, sans-serif'
                        }
                    }, Ext.getBody())
                );

            if (me.html && (me.html !== helperEl.getHTML() 
            		|| me.getWidth() !== (helperEl.dom.clientWidth + offset)))
            {
                helperEl.update(me.html);
                me.setWidth(Ext.Number.constrain(helperEl.dom.clientWidth + 
                	offset, me.minWidth, me.maxWidth));
            }
        }, this);
    }
});

적용 이후 아래와 같이 정상적으로 툴팁이 보여진다.


// 출처 : http://stackoverflow.com/questions/15834689/extjs-4-2-tooltips-not-wide-enough-to-see-contents

Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 16:28
Ext.onReady(function() {
	/***
	 * Date : 2013.05.22
	 * Desc : 아래 코드는 Ext.form.field.Text클래스를 override를 통해 기능을 변경한 예제이다.
	 * 
	 * 		 
	 */
	Ext.define('Cookbook.overrides.TextField', {
		override: 'Ext.form.field.Text',

		onRender: function(){
			/***
			 *  기존 함수의 동작을 확장하기 위해 callParent를 사용한다.
			 *  이때 필요한 인수를 전달하여 원래 함수를 호출할 수 있다.
			 *  아래는 단순히 텍스트를 추가하는 방법을 보여준다.
			 *  간단하게 onRender함수 실행시 간단한 텍스트를 모든 텍스트에서
			 *  동일하게 표시할 수 있도록 되었다.
			 */
			this.callParent(arguments); // executes the Ext.form.field.Text.onRender function
			// Ext.form.field.Text.superclass.onRender.apply(this, arguments); // executes the Ext.form.field.Base.onRender function

			Ext.core.DomHelper.append(this.el, '
' + this.infoText + '
'); } }); Ext.application({ name: 'Customer', launch: function(){ Ext.create('Ext.container.Viewport', { layout: 'fit', items: [{ xtype: 'form', title: 'Security Question Form', defaultType: 'textfield', items: [{ fieldLabel: 'Security Question', name: 'securityQuestion', allowBlank: false, infoText: 'You are required to write a security question for your account.' }, { fieldLabel: 'Security Answer', name: 'securityAnswer', allowBlank: false, infoText: 'Please provide the answer to your security question.' }] }] }); } }); }); // 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 16:27
Ext.onReady(function() {
	/***
	 * Date : 2013.05.22
	 * Desc : Override Ext JS functionality
	 * 		  당신이 ExtJS 프레임웍의 동작을 변경하고자 한다면(권장하지 않음)
	 * 		  직접 프레임웍을 편집하지 않고 override를 이용해여 당신이 만든 클래스를 
	 * 		  통해 쉽게 제어 또는 변경할 수 있다.
	 * 
	 * 		  프레임 워크 코드를 변경하는 것은 강력하게 다른 개발자로 권장하지되는 것은 
	 * 		  변경을 실현하지 않을 수 있으며 불쾌 표준이 아닌 행동에 의해 놀라게 될!
	 * 
	 * 		  override는 기존의 클래스를 가지고도 기존 기능의 동작을 수정하거나 완전히
	 * 		  새로운 것들을 추가 할 수 있습니다. 이것은 크게 프레임워크의 완전히 밖으로 
	 * 		  상자의 동작을 변경하는
	 * 		  매우 간단한 방법을 제공하기 때문이다.
	 * 
	 * 		  Ext JS override는 Ext.Base.override를 칭한다.
	 * 		  Ext.override(Object originalCls, Object overrides) 오리지날 클래스와 합치길 원하는
	 * 		  클래스를 지정하므로서 두개의 클래스가 병합된다.
	 */
	Ext.define('Simple.Class', {
		welcome : function() {
			alert('Welcome to the app');
		}
	});

//	Simple.Class.override({
//		goodBye : function() {
//			alert('Goodbye');
//		},
//
//		runAll : function() {
//			this.welcome();
//			this.goodBye();
//		}
//	});

	Ext.override(Simple.Class, {
		goodBye : function() {
			alert('Goodbye');
		},

		runAll : function() {
			this.welcome();
			this.goodBye();
		}
	});

	var app = new Simple.Class();
	app.runAll(); // Welcome to the app
	// Goodbye

});

// 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94
자바스크립트/Ext JS2013. 5. 22. 16:25
Ext.onReady(function() {
	Ext.define('Cookbook.DisplayPanel', {

		extend : 'Ext.panel.Panel',

		initComponent : function() {

			// apply our configuration to the class
			Ext.apply(this, {
				title : 'Display Panel',
				html : 'Display some information here!',
				width : 200,
				height : 200,
				renderTo : Ext.getBody()
			});

			// call the extended class' initComponent method
			this.callParent(arguments);
		}

	}, function() {
		console.log('Cookbook.DisplayPanel defined!');
	});

	var displayPanel = Ext.create('Cookbook.DisplayPanel');
	displayPanel.show();

	// define our Cookbook.InfoTextField class
	Ext.define('Cookbook.InfoTextField', {

		extend : 'Ext.form.field.Text',
		/***
		 * override했고 this.callparent를 호출하여.
		 * 바로 부모클래스의 onRender메소드가 실행되도록 하였다.
		 */
		onRender : function() {
			this.callParent(arguments);

			// insert our Info Text element
			Ext.core.DomHelper.append(this.getEl(), '
' + this.infoText + '
'); } }, function() { console.log('Cookbook.InfoTextField defined!'); }); // create an instance of our Cookbook.InfoTextField var infoTextField = Ext.create('Cookbook.InfoTextField', { renderTo : Ext.getBody(), fieldLabel : 'Username', infoText : 'Your Username must be at least 6 characters long.' }); // infoTextField.show(); }); // 출처 : Ext JS4 Web Application Development Cookbook
Posted by 베니94