반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

Sencha Touch 2 Tutorial - View - 01

2012. 3. 8. 21:34 | Posted by 솔웅


반응형
이번주에 사무실이 이사갑니다.
짐을 다 싸 놔서 인터넷도 못하네요.

이제 봄도 되고 사무실도 새로운 곳으로 옮겨지니 새 기분으로 열심히 일 하자고 다짐해 보게 됩니다.

오늘은 Sencha Touch 2.0의 View에 대해서 공부하겠습니다.
오늘 그 내용을 다 다루지는 못하구요. 두번에 나눠서 다루겠습니다.

======= o ======= o ======= o ======= o ======= o

Using Views in your Applications

유저 입장에서 보면 어플리케이션은 단지 view의 모임들일 뿐입니다. 앱에 Model과 Controller가 아주 중요한 역할을 하지만 View가 바로 유저에게 직접 보여지는 부분입니다. 오늘은 이런 뷰를 어떻게 만드는지에 관해 공부해 보겠습니다.

Using Existing Components

View를 생성하는 가장 쉬운 방법은 Ext.create를 사용하는 겁니다. 예를 들어 HTML과 Panel을 만들기를 원한다면 아래처럼 하면 됩니다.

Ext.create('Ext.Panel', {
    html: 'Welcome to my app',
    fullscreen: true
});



예제를 보시면 HTML이 들어간 이 Panel은 전체 화면을 차지하도록 돼 있습니다. Panel이외에도 Sencha Touch에서 제공하는 모든 컴포넌트들을 이런식으로 사용하시면 됩니다. 하지만 바람직한 방법은 특별히 구현하고자하는 것을 subclass로 만들고 나서 생성하는 방법입니다. 아래 예제를 보시죠.

Ext.define('MyApp.view.Welcome', {
    extend: 'Ext.Panel',

    config: {
        html: 'Welcome to my app',
        fullscreen: true
    }
});

Ext.create('MyApp.view.Welcome');

phone에 나오는 화면은 이전과 똑 같습니다. 하지만 다른 점은 새로운 컴포넌트를 가지게 됐습니다. 이 컴포넌트 안에서 여러 작업을 할 수 있습니다. 이것이 일반적으로 앱을 만들때 사용하는 패턴입니다. component가 있는 subclass를 만들고 instance는 나중에 만드는 겁니다. 그럼 어떤게 바뀌었는지 살펴 볼까요?

- Ext.define은 새로운 class를 만들 때 사용합니다. 그리고 그 안에서 extend를 이용해서 Ext.panel 같은 컴포넌트들을 불러와서 사용할 수 있습니다. (Componen에는 4가지가 있는데 Navigation, Store-bound, Form, General Components 가 있습니다. 자세한 내용은 여기 를 참고하세요.)
- MyApp.view.MyView 형식으로 새 뷰 클래스를 만들었습니다. 이 형식은 개발자 마음대로 사용하셔도 되지만 이 형식을 유지할 것을 권장합니다.
- 이 새 클래스에서 우리는 config 를 정의했습니다.
이 config는 subclass의 config block에서 정의하셔도 되고 create() 로 instance를 만들 때 정의하셔도 됩니다.

아래 예제에서는 subclass가 아니라 create() 안에서 object를 pass하는 것을 보여 줍니다.
결과 화면은 CSS가 적용되서 보기 좋은 폰트가 display 됩니다.




A Real World Example

아래 예제는 Sencha Touch 의 Twitter 앱에서 실제 사용한 view class 중 한 부분 입니다.
Ext.define('Twitter.view.SearchBar', {
    extend: 'Ext.Toolbar',
    xtype : 'searchbar',
    requires: ['Ext.field.Search'],

    config: {
        ui: 'searchbar',
        layout: 'vbox',
        cls: 'big',

        items: [
            {
                xtype: 'title',
                title: 'Twitter Search'
            },
            {
                xtype: 'searchfield',
                placeHolder: 'Search...'
            }
        ]
    }
});

이 예제는 바로 전 예제와 같은 패턴을 따르고 있습니다. 새로운 클래스로 Twitter.view.SearchBar를 생성했습니다. 이 클래스는 framwork의 Ext.Toolbar 클래스를 extends 했습니다. 그리고 몇가지 configuration 옵션이 있습니다. layout하고 items array 입니다.

몇개 새롭게 나온 옵션들에 대해서 알아보죠.

: requires - items array를 위해 searchbar를 사용하기 때문에 이 새 뷰에 Ext.field.Search 클래스를 사용할거라고 알려줘야 합니다.
: xtype - 새 클래스 만의 xtype을 줍니다. 간편하게 configuration object를 생성하도록 합니다. 이렇게 함으로서 우리는 여러 방법으로 새로운 뷰 클래스의 인스턴스를 생성할 수 있습니다. 아래와 같이 이 xtype을 이용하시면 편리하게 방금 만든 새로운 클래스를 쉽게 재 사용하실 수 있습니다.

//creates a standalone instance
Ext.create('Twitter.view.SearchBar');

//alternatively, use xtype to create our new class inside a Panel
Ext.create('Ext.Panel', {
    html: 'Welcome to my app',

    items: [
        {
            xtype: 'searchbar',
            docked: 'top'
        }
    ]
});

======= o ======= o ======= o ======= o ======= o

다음 시간에 나머지 View 부분 마저 다루겠습니다.

오늘도 추천 한방씩 ~~~~~ ~~~~~ 부탁드려여...
반응형


반응형
Corona SDK에서 명예 홍보 대사 임명됐다는 메일을 담당자로부터 그냥 개인적으로 들었는데 오늘 공식적으로 임명 됐다는 메일이 왔어요. :)
원래는 한달 쯤 전에 공식 발표 될 거라고 했는데... 이것 저것 준비 하다가 늦어졌다고 하네요.

아래가 메일 중 일 부분이예요.

======== o ========= o ========= o ========= o ========= o

Dear Corona Ambassador,
코로나 대사 귀하

Welcome to the Corona Ambassador Program! You are part of our very first batch of 42 Corona Ambassadors! We have members from all over the world, from San Jose to Sydney.

코로나 대사 프로그램에 오신것을 환영합니다. 당신은 첫번째 Corona 대사로 임명된 42명중 한명입니다. 코로나 대사는 산호세부터 시드니까지 전 세계에 걸쳐 있습니다.

Thank you for joining and for bearing with us while we rolled this out. It has taken us longer than we'd like, but we've been very busy. As you know, we are seeing more and more activity around Corona every single day and there are many things to do.

이렇게 참여해 주시고 우리가 이 일을 다 처리할 때까지 기다려 주셔서 감사합니다. 당초 예상보다 늦어졌습니다. 아주 바빴거든요. 아시다시피 매일매일 코로나 관련 여러 활동들이 있었고 많은 처리 해야 할 일들이 있었습니다.

In any case, we are excited to be officially starting the program. As I mentioned to you when we spoke, our goals are to spread the word about Corona SDK, develop closer relationships with you, our top developers, and to help you achieve your goals - from just meeting other Corona developers to discussing app ideas to growing your businesses.

어쨌든 이렇게 공식적으로 코로나 대사 프로그램을 시작할 수 있어서 매우 기쁩니다. 당초 말씀 드렸듯이 우리의 목표는 Corona SDK를 전 세계에 홍보하는 것이고 개발자들과 대사간의 긴밀한 관계를 맺도록 하는 것입니다. 이러한 목표를 달성하기 위해서 우리 코로나의 top 개발자들이 당신을 도울 겁니다. 단순한 코로나 개발자들의 모임에서부터 코로나를 사용하는 분들의 비지니스 성장을 위한 앱 아이디어관련 토론 등 여러 분야에서 도움을 드릴겁니다.

------------------

In exchange, we'd like to work with you to organize events/meetups in your area every 30 to 60 days - we'll help promote these events and cover costs. 
Also, feel free to send me any comments/ideas/questions you may have. We are open to anything that will help grow this program and spread the word about Corona.

이를 위해 여러분도 30일에서 60일에 한번은 코로나 관련한 이벤트나 모임을 만드시기를 부탁드립니다. 이 이벤트와 비용에 대해 일정 부분 도움을 드리겠습니다.
그리고 어떤 코멘트,아이디어, 질문 이라도 좋으니 많은 의견 보내 주세요. 이 프로그램이 좀 더 활성화 될 수 있고 Corona가 전 세계에 좀 더 많이 퍼질 수 있다면 어떤 의견이라도 받아들이겠습니다.

--------------------

Thanks again and I'm looking forward to working with all of you!
다시 한번 감사드리며 여러분과 같이 일하게 돼 기쁘다는 말씀 전해 드립니다.

David

======== o ========= o ========= o ========= o ========= o

이렇게 공식적으로 대사 임명 메일을 받으니 아주 기분이 좋네요.

코로나에서는 대사가 진행하는 모임의 의견이나 질문을 듣는 공식적인 루트를 마련해 준다고 했습니다.

그러니 여러분이 개발하시면서 아니면 다른 코로나 관련한 질문이 있으시면 제가 정리해서 질문을 할 수 도 있습니다. 그러면 좀 더 성의있고 빠른 답변을 받을 수 있을 것으로 기대합니다.

제대로 코로나 SDK 개발자 모임을 만들려고 합니다.

혹시 Tistory에서 특정 메뉴를 membership으로 운영하는 방법이 있는지 모르겠습니다.
아니면 카페를 만들어야 하는지.. 그리고 제가 미국에 있어서 Online 모임을 할 수 있는 방법이 무엇이 있는지 등등에 대해 여러분의 조언을 바랍니다.

membership이 완성이 되면 따로 online모임을 할 수도 있고 서울이나 지방 아니면 여기 뉴저지나 뉴욕에 사는 멤버들끼리 모임을 유도할 수도 있을 것 같구요.

물론 그 모임에 어떤 지원을 할 수 있을지 제가 코로나 측에 알아봐서 지원을 해 드릴 수도 있습니다.

혹시 member가 되시고 싶은 분 여기 댓글에 남겨 주세요. 그리고 모임을 구성할 정도가 되면 어떻게 모임을 이끌어 나가면 좋을지에 대한 의견 있으시면 올려주시면 아주 도움이 많이 되겠습니다.

저도 많이 고민해 보겠습니다.

같이 코로나 SDK 개발의 전문가가 되고 싶으신 분 여기여기 모이세요. ~~~~~~~



~~~~~~~~~~
반응형

Sencha Touch 2 Tutorial - Controllers -

2012. 3. 6. 12:19 | Posted by 솔웅


반응형
Controllers

Controller는 어떤 event가 일어 났을 때 다른 어떤 동작이 일어날 수 있도록 Control 하는 역할을 합니다. 만약 앱에 로그아웃 버튼이 있다면 유저는 이 버튼을 tap 할테고 Controller는 이 버튼에 대한 tap event를 listening 하고 있다가 이벤트가 발생하면 로그아웃 시키는 동작을 하도록 합니다. 이러한 기능은 View 클래스가 보여 주는 데이터를 변경하도록 할 수 있고 또 Model 클래스가 데이터를 로딩,저장 등의 동작을 할 수 있도록 해 줍니다. Controller는 이 사이에서 그런 동작들이 자연스럽게 이뤄질 수 있도록 Control 해 줍니다.

Relation to Ext.app.Application

Controller는 어플리케이션의 context 안에 존재합니다. 하나의 어플리케이션은 대개 어떤 특정한 부분을 handle 하는 여러 Controller들로 구성 돼 있습니다. 예를 들어 온라이 쇼핑 싸이트에서 주문을 하는 앱을 생각해 보면 이 앱에는 주문과 고객 그리고 상품들에 대한 Controller들이 있을 겁니다.

모든 컨트롤러는 그 어플리케이션의 Ext.app.Application.controller config에서 정해 주시면 됩니다. 이 어플리케이션은 각 컨트롤러를 자동적으로 instantiate 시켜주고 계속 참조하게 됩니다. 그래서 컨트롤러를 직접 instantiate 시키는 상황은 특별한 경우에만 한합니다. convention에 의해 컨트롤러들은 명명되는데 대개 Model 작업 수행 이전에 복수개의 컨트롤러들에 대해 이 작업이 이뤄집니다. 예를 들어 MyApp이라는 앱이 있고 여기에 컨트롤러가 Product를 관리한다면 convention은 app/controller/Products.js라는 파일에 MyApp.controller.Products 라는 클래스를 생성합니다.

Launching

어플리케이션이 launch 될 때 4가지의 주요 단계를 거치게 됩니다. 2가지는 컨트롤러 안에서 행해집니다. 첫번째로 각각의 컨트롤러는 init 함수를 정의할 수 있게 됩니다. 이것은 Application launch 함수 이전에 call 됩니다. 두번째는 Application과 Profile launch 함수가 call 된 이후인데요, 프로세스의 마지막 단계로 컨트롤러의 launch 함수가 call 됩니다.

    Controller#init functions called
    Profile#launch function called
    Application#launch function called
    Controller#launch functions called

대개 Controller-specific launch 로직은 Controller의 launch 함수 안에 있어야 합니다. 왜냐하면 이것은 Application과 Profile launch 함수 이후에 call 되기 때문입니다. 바로 이 시점에 initial UI가 있게 됩니다. 만약 app launch 이전에 Controller-specific processing이 필요하다면 Controller init 함수를 implement 할 수 있습니다.

Refs and Control

컨트롤러에서 중요한 두가지는 refscontrol configuration입니다. 이 둘은 앱의 Component들에 쉽게 reference들을 얻을 수 있게 해주고 어떤 이벤트가 발생하면 이에 대해 어떤 동작이 일어날 수 있도록 해 줍니다. refs 먼저 보겠습니다.

Refs

Refs는 아주 강력한 ComponentQuery 신택스에 영향을 주는것으로 각 페이지에 쉽게 Comopnent들을 위치시킬 수 있도록 합니다. 각 콘트롤러에 대해 원하는 만큼의 refs를 정의할 수 있습니다. 예를 들어 아래 예제에서는 maniNav라는 아이디라는 Component를 찾는 nav라 불리는 ref를 정의합니다. 그 다음에 그 아래에 addLogoutButton 안의 ref를 사용합니다.

Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            nav: '#mainNav'
        }
    },

    addLogoutButton: function() {
        this.getNav().add({
            text: 'Logout'
        });
    }
});

대개 ref는 key/value 조합입니다. 키(위의 경우 nav)는 reference의 이름으로 ref를 생성하기 위해 사용됩니다. 그리고 값(위의 경우 #mainNav)는 ComponentQuery selector로 Componet를 찾을 때 사용 됩니다.

그 아래에 addLogoutButton이라는 간단한 함수를 call 했습니다. 이것은 getNav 함수를 발생시키면서  이 ref를 사용하게 될 겁니다. 이런 getter 함수들은 당신이 정의한 refs를 바탕으로 발생됩니다. 이 함수의 이름은 get 다음에 ref의 대문자(NAV)를 붙여서 이름을 만드는 규칙을 따릅니다. 이 경우엔 nav reference가 툴바이고 함수가 호출 돼었을 때 이 툴바에 Logout 버튼을 추가하도록 했습니다. 이 ref는 아래와 같이 툴바를 인식할 겁니다.

Ext.create('Ext.Toolbar', {
    id: 'mainNav',

    items: [
        {
            text: 'Some Button'
        }
    ]
});

우리가 addLogoutButton 함수를 run 할 때 이미 툴바가 생성돼 있었다고 가정합시다. (이 과정이 어떻게 진행되는지는 나중에 볼 겁니다.) 이 경우에는 두번째 버튼이 생길 겁니다.

Advanced Refs

Refs는 name과 selector 이후에 몇개의 추가 옵션을 설정할 수 있습니다. autoCreate, xtype 등이 그것인데 대부분 같이 사용 됩니다.

Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            nav: '#mainNav',

            infoPanel: {
                selector: 'tabpanel panel[name=fish] infopanel',
                xtype: 'infopanel',
                autoCreate: true
            }
        }
    }
});

이제 우리의 Controller에 두번째 ref를 add 했습니다. 마찬가지로 이름이 key 입니다. 이경우에는 infoPanel이 되겠죠. 여기서는 value(값) 대신 object를 pass 하고 있습니다. 조금 더 복잡한 selector query도 있죠? 한번 상상해 보세요. 앱이 tab panel을 가지고 있고 그 tab 판넬의 아이템 중 하나가 이름이 fish라구요. 위 예제의 selector는 tab panel 아이템 안에 infopanel이라는 xtype을 가진 Component를 match 할 겁니다.

이 예제에서 좀 다른 점은 infopanel이 fish panel 안에 존재하지 않는다면 Controller안에서 this.getInforPanel을 call 할 때 자동적으로 생성하게 될 겁니다. 그 이유는 이 컨트롤러의 selector가 아무것도 return 하지 않고 event 시 instantiate 하도록 xtype을 제공하기 때문입니다.

Control

refs config와 짝을 이루는 것이 바로 control입니다. 콘트롤은 콤포넌트에 의해 일어나는 이벤트나 Controller의 어떠한 react를 listening 하는 수단입니다. Control은 자신의 key로 Component ComponentQuery selectors 와 refs를 받습니다. 아래 예제가 있습니다.

Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        control: {
            loginButton: {
                tap: 'doLogin'
            },
            'button[action=logout]': {
                tap: 'doLogout'
            }
        },

        refs: {
            loginButton: 'button[action=login]'
        }
    },

    doLogin: function() {
        // called whenever the Login button is tapped
    },

    doLogout: function() {
        // called whenever any Button with action=logout is tapped
    }
});

이 예제에서 우리는 두개의 control을 정의했습니다. 하나는 loginButton ref를 위한 것이고 다른 하나는 logout 기능을 할 한 버튼을 위한 겁니다. 이 각각의 정의에 하나의 이벤트 핸들러를 넣었습니다. 바로 tap 이벤트에 대해 listening 하도록 했습니다. 이 버튼들에 tap 이벤트가 발생하면 어떤 동작이 일어날 겁니다. tap 다음에 doLogin과 doLogout이 있죠? 이건 함수 이름입니다. 어딘가에 이 함수가 있고 그 안에 필요한 기능들이 코딩 돼 있을 겁니다. 중요한 부분이죠.

각각의 control 정의할 때 원하는 만큼의 이벤트 리스너를 달 수 있습니다. 그리고 키로서 key로서 ComponentQuery selector와 refs를 섞어서 매치할 수 도 있습니다.

Routes

Sencha Touch 2에서 Controller는 route를 direct하게 명시할 수 있습니다. 이것은 앱 안에서 history support 제공을 가능하게 하며 앱 내에 어떤 페이지든지 직접 링크를 걸어서 가도록 할 수 있습니다. 이것이 route를 제공하기 때문에 가능한 일들 입니다.

예를 들어 로그인과 유저 프로파일을 보여주는 일을 담당하는 Controller가 있다고 합시다. 그리고 이 화면이 url로 접근 할 수 있도록 하고 싶다고 합시다. 아래와 같이 하시면 될 겁니다.

Ext.define('MyApp.controller.Users', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'login': 'showLogin',
            'user/:id': 'showUserById'
        },

        refs: {
            main: '#mainTabPanel'
        }
    },

    // uses our 'main' ref above to add a loginpanel to our main TabPanel (note that
    // 'loginpanel' is a custom xtype created for this application)
    showLogin: function() {
        this.getMain().add({
            xtype: 'loginpanel'
        });
    },

    // Loads the User then adds a 'userprofile' view to the main TabPanel
    showUserById: function(id) {
        MyApp.model.User.load(id, {
            scope: this,
            success: function(user) {
                this.getMain().add({
                    xtype: 'userprofile',
                    user: user
                });
            }
        });
    }
});

위에서 명시한 routes는 간단하게 브라우저 address bar를 Controller 함수로 매핑 시킵니다. 이 routes는 login route 같이 http://myapp.com/#login에 매치 되는 간단한 텍스트가 될 수도 있습니다. 또는 http://myapp.com/#user/123 같이 url에 매치되는 user/:id route 같이 wildcard를 가지고 있을 수도 있습니다. 주소가 바뀔 때마사 콘트롤러는 명시된 함수를 자동적으로 call 합니다.

showUserById 함수에서 유저 인스턴스를 첫번째로 로드하는 부분을 주의해서 보세요. route를 사용할 때마다 이 함수는 그것과 관련한 데이터나 상태 저장에 대해 완료하는 책임을 갖는 route에 의해 불려지게 됩니다. 유저가 이 url을 다른 사람에게 전달할 수도 있고 아니면 단순하게 그 페이지를 refresh 할 수도 있기 때문입니다. 그래서 지금 로드 했던 것들을 cache에서 지워버릴 필요가 있기 때문입니다. route와 관련해서 restoring state에 대한 좀 더 자세한 설명은 application architecture guides에서 보실 수 있습니다.

Before Filters

마지막으로 Routing의 context내에서 Controller가 제공하는 것은  routes를 작성하기 이전에 작성되는 filter 함수 정의 before 입니다.

Ext.define('MyApp.controller.Products', {
    config: {
        before: {
            editProduct: 'authenticate'
        },

        routes: {
            'product/edit/:id': 'editProduct'
        }
    },

    // this is not directly because our before filter is called first
    editProduct: function() {
        //... performs the product editing logic
    },

    // this is run before editProduct
    authenticate: function(action) {
        MyApp.authenticate({
            success: function() {
                action.resume();
            },
            failure: function() {
                Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
            }
        });
    }
});

유저가 http://myapp.com/#product/edit/123같이 url로 navigate할 때마다 컨트롤러의 authenticate 함수가 불려질겁니다. 그리고 만약 before 필터가 존재하지 않을 경우 Ext.app.Action을 pass할 겁니다. Action은 단순하게 Controller, function(이 예제의 경우 editProduct)를 표현합니다.  rmflrh url에 있는 ID 같은 다른 데이터도 표현합니다.

이제 필터는 동기적으로나 비동기적으로 필요한 일을 할 수 있습니다. 이 예제의 경우에는 어플리케이션의 유저가 제대로 로그인 정보를 주었는지에 대한 authenticate 함수를 실행합니다. 이 동작은 서버에 있는 정보와의 비교가 필요하기 때문에 AJAX request를 사용할 것이고 비동기적으로 작동될 겁니다. 인증이 성공하면 action.resume() 함수를 call 해서 다음 동작을 이어 가게 됩니다. 만약 인증되지 않으면 다시 로그인 하도록 해야 합니다.

before 필터는 어떤 특정 action이 행해지기 이전에 추가적인 클래스들을 load하기 위해 사용 될 수 있습니다. 예를 들어 어떤 동작은 드물게 실행 되어서 필요한 상황이 될 때까지 로딩을 하지 않고 싶은 경우가 있을 수 있습니다. 그러면 애플리케이션이 시작할 때 좀 더 빠르게 시작되게 할 수 있겠죠. 이를 위해 간단히 필요할 때 로드될 수 있도록 Ext.Loader를 사용하면 됩니다.

각 action에 대해 원하는 만큼의 before 필터가 명시 될 수 있습니다. 1개 이상의 필터를 사용하려면 배열을 pass 해 주면 됩니다.

Ext.define('MyApp.controller.Products', {
    config: {
        before: {
            editProduct: ['authenticate', 'ensureLoaded']
        },

        routes: {
            'product/edit/:id': 'editProduct'
        }
    },

    // this is not directly because our before filter is called first
    editProduct: function() {
        //... performs the product editing logic
    },

    // this is the first filter that is called
    authenticate: function(action) {
        MyApp.authenticate({
            success: function() {
                action.resume();
            },
            failure: function() {
                Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
            }
        });
    },

    // this is the second filter that is called
    ensureLoaded: function(action) {
        Ext.require(['MyApp.custom.Class', 'MyApp.another.Class'], function() {
            action.resume();
        });
    }
});

이 필터들은 순서대로 call 됩니다. 그리고 다음 단계로 가기 위해서 반드시 각각 action.resume()을 call 해야 합니다.


Profile-specific Controllers

Superclass, shared stuff:

Ext.define('MyApp.controller.Users', {
    extend: 'Ext.app.Controller',

    config: {
        routes: {
            'login': 'showLogin'
        },

        refs: {
            loginPanel: {
                selector: 'loginpanel',
                xtype: 'loginpanel',
                autoCreate: true
            }
        },

        control: {
            'logoutbutton': {
                tap: 'logout'
            }
        }
    },

    logout: function() {
        // code to close the user's session
    }
});

Phone Controller:

Ext.define('MyApp.controller.phone.Users', {
    extend: 'MypApp.controller.Users',

    config: {
        refs: {
            nav: '#mainNav'
        }
    },

    showLogin: function() {
        this.getNav().setActiveItem(this.getLoginPanel());
    }
});

Tablet Controller:

Ext.define('MyApp.controller.tablet.Users', {
    extend: 'MyApp.controller.Users',

    showLogin: function() {
        this.getLoginPanel().show();
    }
});

===== o ===== o ===== o ===== o ===== o =====

오늘도 개념적인 부분을 많이 다뤘습니다. 다음시간에는 View에 대해서 다룰 겁니다.
제목에서 알 수 있듯이 다음 시간에는 코딩하고 결과를 눈으로 확인하면서 할 수 있을 겁니다.
어쨌든 오늘 다룬 Controller도 아주 중요한 부분이니까 어느정도 이해 될 때까지 읽어 보고 다음으로 넘어가야겠습니다.


반응형