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

최근에 받은 트랙백

글 보관함


어제까지 잘 실행해 보셨나요?

저의 경우엔 textfield 하고 textarea 표시할 때 label (Title, Narrative) 가 안나오더라구요.
그리고 상단 툴바에 home 버튼만 나오고 save 버튼은 안나오구요.
그리고 하단 버튼에 trash 버튼도 안 나오고......


원래는 이렇게 나와야 되는데 아래처럼 나오네요.


저 왼쪽 스크롤을 내리면은 아래 툴바가 나오긴 하는데 trash 버튼은 안 나옵니다.

브라우저 버전일까 싶어서 크롬 최신버전으로 깔아도 똑 같은 문제네요.
이 소스가 원래 Sencha Touch 1.1.1 버전을 기반으로 한 거라서 따로 인터넷 검색해서 1.1.1 버전의 css 하고 js 파일을 다운 받아 썼는데... 그 파일 버전이 잘못 된건지......

여러분은 어떻게 나오시나요?

일단 오늘 Sencha Touch 의 Notes Application 마지막 부분을 정리하겠습니다.
잘 안되는 부분은 다시 해결해 봐야겠습니다.
(맨 아래 최종버전 압축파일 올리겠습니다.)
혹시 원래 설계대로 잘 되시는 분 있으면 연락 주세요.

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

이번 강좌가 Sencha Touch 로 첫번째 앱 만들기 마지막 시간입니다.
지난 시간에는 Note Editor 와 새로운 Notes를 생성하는 기능을 구현해 봤습니다.
이제 수정하고 delete하는 기능을 살펴 보겠습니다.

***** Disclosure events in a Sencha Touch List

유저가 이 앱을 사용하면서 disclosure 버튼(화살표 버튼)을 누르게 되면 해당 Note의 제목과 내용이 보여지게 됩니다.



우리는 이 기능을 notes list의 onItemDisclosure 핸들러를 통해 구현할 수 있습니다.

NotesApp.views.notesList = new Ext.List({
    id: 'notesList',
    store: 'NotesStore',
    onItemDisclosure: function (record) {
        var selectedNote = record;
        NotesApp.views.noteEditor.load(selectedNote);
        NotesApp.views.viewport.setActiveItem('noteEditor', { type: 'slide', direction: 'left' });
    },
    itemTpl: '
<div class="list-item-title">{title}</div>' +
        '<div class="list-item-narrative">{narrative}</div>',
    listeners: {
        'render': function (thisComponent) {
            thisComponent.getStore().load();
        }
    }
});

이 핸들러 함수는 파라미터로서 선택된 note를 받습니다. 이 핸들러에서 우리가 구현해야 할 것은 에디터의 load()메소드를 사용해서 note를 load 하는 겁니다.
그리고 나서 viewport의 setActiveItem()을 호출해서 Note Editor의 view를 active 시킵니다.

***** Removing records from a data store

notes를 지우는 기능도 아주 간단히 구현할 수 있습니다.
화면 아래 툴바에 있는 휴지통 버튼이 이 기능을 실행하도록 할 겁니다.
아래처럼 이 버튼 핸들러를 수정합니다.

NotesApp.views.noteEditorBottomToolbar = new Ext.Toolbar({
    dock: 'bottom',
    items: [
        { xtype: 'spacer' },
        {
            iconCls: 'trash',
            iconMask: true,
            handler: function () {

                var currentNote = NotesApp.views.noteEditor.getRecord();
                var notesList = NotesApp.views.notesList;
                var notesStore = notesList.getStore();

                if (notesStore.findRecord('id', currentNote.data.id)) {
                    notesStore.remove(currentNote);
                }

                notesStore.sync();

                notesList.refresh();
                NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction:

'right' });
            }
        }
    ]
});

현재의 note에 대한 reference 정보들을 확보한 다음에 우리는 store의 findRecord() 함수를 사용해 에디터에 로드된 note를 찾아서 지울겁니다.
그리고 나서 sync()를 호출해서 이 삭제작업에 대해 commit 합니다. 그리고 다시 리스트를 render 해서 새로운 Notes List view를 보여줍니다.

이 기능은 Save Note 부분에서 처리됐던 과정이랑 비슷합니다. 단지 saving 이 아니라 deleteing 만 달르 뿐입니다.

***** Grouping items in a Sencha Touch List

이제 마지막으로 남은것은 Notes List view 에서 날짜별로 그루핑 하는 겁니다. 유저가 note들을 날짜별로 구분해서 보면 훨씬 더 보기 좋을테니까요.

첫번째로 Ext.List에게 아이템들이 group화 되어야 한다고 알려줘야 합니다. 이것은 grouped config 옵션을 사용해서 구현할 수 있습니다.

NotesApp.views.notesList = new Ext.List({
    id: 'notesList',
    store: 'NotesStore',
    grouped: true,
    emptyText: '<div style="margin: 5px;">No notes cached.</div>',
    onItemDisclosure: function (record) {
        var selectedNote = record;
        NotesApp.views.noteEditor.load(selectedNote);
        NotesApp.views.viewport.setActiveItem('noteEditor', { type: 'slide', direction: 'left' });
    },
    itemTpl: '<div class="list-item-title">{title}</div>' +
        '<div class="list-item-narrative">{narrative}</div>',
    listeners: {
        'render': function (thisComponent) {
            thisComponent.getStore().load();
        }
    }
});

그 다음엔 NotesStore의 getGroupStrint() 함수를 오버라이드 해야 합니다.

Ext.regStore('NotesStore', {
    model: 'Note',
    sorters: [{
        property: 'date',
        direction: 'DESC'
    }],
    proxy: {
        type: 'localstorage',
        id: 'notes-app-store'
    },
    getGroupString: function (record) {
        if (record && record.data.date) {
            return record.get('date').toDateString();
        } else {
            return '';
        }
    }
});

이제 groupField 프로퍼티와 getGroupString() 함수를 이용해서 구체적인 사항들을 정의하실 수 있습니다.

getGroupString() 함수는 store의 data model 프로퍼티에 근거한 string을 리턴합니다.
이 앱의 경우는 그룹의 헤더로 note의 date 값을 사용할 겁니다.
에뮬레이터로 보면 아래와 같이 나올 겁니다.



***** We made it!


이제 완성했습니다. 아주 간단한 Sencha Touch 애플리케이션이죠? 그래서 Sencha Touch 프레임워크에 대해 쉽게 이해할 수 있을 것 같습니다.
이제 첫번째 앱을 만들면서 감을 잡았으니 Sencha Touch로 된 좀 더 복잡한 애플리케이션을 만들 수 있을 겁니다.

아래 지금까지 진행한 소스가 있습니다.
다운받아서 실행해 보세요.


이걸 실행해보면 처음에 얘기했던대로 제 브라우저에서는 label 도 안나오고 save 버튼하고 trash 버튼 모두 안나오네요.

여러분은 제대로 나오시는지 궁금하네요.
sencha-touch.css 하고 sencha-touch-debug.js 도 다른 버전으로 바꿔보고 브라우저도 여러군데서 실험해 봐야겠습니다.

성공하신분 댓글로 정보 부탁드립니다.

다음엔 Sencha Touch 최신버전 (2.0) 에 맞는 예제소스로 공부해 볼 생각입니다.

추천추천 부탁드려요..~~~~~~~~~~~
반응형

Comment

  1. 훅스 2012.03.22 23:11

    잘 봤습니다.
    따라 했더니 잘 나오네요...^^;
    선언 순서나 css 구현이 잘못되었는지 의심스럽네요


지난 시간에는 New 버튼을 달고 더미 데이터를 넣어서 List 를 출력해 봤습니다.
잘 되셨나요?

지난주까지 진행한 소스코드 아래에 있습니다.
필요하신 분은 받아서 보세요.


오늘은 Note Editor 부분을 하겠습니다.
Notes List 에서 Note Editor 화면으로 전환하고 새 데이터를 넣고 저장하고 이것을 List 로 새로 출력하는 기능을 할 겁니다.
이 과정에서 validation도 체크하는 기능도 다룰거구요.

아래 오늘의 내용을 보시죠.

Writing a Sencha Touch Application, Part 3

Part 1,2 에서는 Notes 앱 중에 Notes List view 부분을 다뤘습니다. 오늘은 Note Editor view를 다루겠습니다.
타이틀은 Edit Note 가 될 텐데요. Note의 생성, update, 삭제 기능이 있을 겁니다.
아래 Mock up 이미지와 완성 화면이 있습니다.








***** Creating a Sencha Touch Form Panel

Note Editor mockup을 보면 우리는 툴바와 필드들을 만들어야 합니다.
우선 form field들 부터 만들겠습니다.

NotesApp.views.noteEditor = new Ext.form.FormPanel({
    id: 'noteEditor',
    items: [
        {
            xtype: 'textfield',
            name: 'title',
            label: 'Title',
            required: true
        },
        {
            xtype: 'textareafield',
            name: 'narrative',
            label: 'Narrative'
        }
    ]
});


이 필드들을 만들기 위해 Ext.form.FormPanel 클래스를 사용했습니다. 센차터치에서 form 필드들을 만들 때 가장 손쉽게 만들 수 있는 방법입니다.
제목은 textfield를 사용하고 내용을 넣는 공간은 Text field를 사용합니다.
title 부분에 required 를 true로 했습니다. 반드시 이곳에 값을 넣어야 한다는 겁니다. 디비의 not null 이죠. 나중에 save 하는 단계에서 이곳에 값을 넣지 않으면 어떻게 되는지 보실 수 있습니다.

툴바를 넣기 전에 이 form들의 모습이 어떤지 미리 보면 좋겠죠? viewport 부분을 약간 수정해서 이 form이 보이도록 해 보죠.
viewport의 items 부분을 수정해 아래처럼 수정해 보세요. 그러면 지난번에 만들었던 list가 아니라 edit form이 나올겁니다.

NotesApp.views.viewport = new Ext.Panel({
    fullscreen: true,
    layout: 'card',
    cardAnimation: 'slide',
    items: [NotesApp.views.noteEditor] // TODO: revert to [NotesApp.views.notesListContainer]
});

제대로 됐다면 아래처럼 보일겁니다.




***** Adding top and bottom toolbars to a Sencha Touch Panel

이제 툴바를 만들 차례입니다.
첫번째 툴바는 Home 과 Save 버튼이 있는 위쪽 툴바입니다.

NotesApp.views.noteEditorTopToolbar = new Ext.Toolbar({
    title: 'Edit Note',
    items: [
        {
            text: 'Home',
            ui: 'back',
            handler: function () {
                // TODO: Transition to the notes list view.
            }
        },
        { xtype: 'spacer' },
        {
            text: 'Save',
            ui: 'action',
            handler: function () {
                // TODO: Save current note.
            }
        }
    ]
});

위 소스 콛를 보시면 툴바를 만들면서 ui config 옵션을 사용하신 걸 보실 수 있을 겁니다. (back, action 으로 정의했죠?) home 버튼에는 back 이라고 정의했습니다. 왜냐하면 이 버튼을 누르면 back 해서 main view 로 갈 것이기 때문입니다. 그리고 save 버튼에는 action이라고 정의했는데요. 이것은 유저가  이 버튼을 누르면 note를 save 할 거라는 겁니다. 이 기능이 가장 중요한 기능 중 하나죠?



화면 아래에 있는 툴바에는 휴지통 버튼이 들어갈 겁니다. 이 버튼을 누르면 해당 note 가 delete 되겠죠?
NotesApp.views.noteEditorBottomToolbar = new Ext.Toolbar({
    dock: 'bottom',
    items: [
        { xtype: 'spacer' },
        {
            iconCls: 'trash',
            iconMask: true,
            handler: function () {
                // TODO: Delete current note.
            }
        }
    ]
});

여기에 몇가지 주의하실 부분이 있습니다. 첫번째로 dock config를 어떻게 사용했는지 보세요. 화면 아래에 배치하기 위해 bottom을 사용했습니다. 그리고 iconCls와 iconMask config 옵션을 보세요. 이 기능들은 버튼 안에 trash icon을 render 하기 위한 옵션들입니다.



이제 툴바를 add 하실 수 있습니다.

NotesApp.views.noteEditor = new Ext.form.FormPanel({
    id: 'noteEditor',
    items: [
        {
            xtype: 'textfield',
            name: 'title',
            label: 'Title',
            required: true
        },
        {
            xtype: 'textareafield',
            name: 'narrative',
            label: 'Narrative'
        }
    ],
    dockedItems: [
            NotesApp.views.noteEditorTopToolbar,
            NotesApp.views.noteEditorBottomToolbar
        ]
});

약간 코드를 수정해서 지금까지 한 작업을 화면으로 볼 수 있도록 해 보죠.

NotesApp.views.viewport = new Ext.Panel({
    fullscreen: true,
    layout: 'card',
    cardAnimation: 'slide',
    items: [NotesApp.views.noteEditor] // TODO: revert to [NotesApp.views.notesListContainer]
});

성공했으면 아래와 같은 화면을 보실 수 있을 겁니다.




아주 훌륭하죠?

지금까지 우리는 Notes List와 Note Editor 뷰를 만들었습니다. 이제 필요한 것은 이 앱의 workflow 입니다. 뷰 이외에 다른 비지니스 로직을 어떻게 구현하느냐를 말하는 것이죠. 우선 첫번째 기억할 비지니스 로직(Navigate screen) 은 Notes List 에서 New 버튼을 누르면 Notes Edit View 로 간다는 겁니다.



****** How to change views in a Sencha Touch application

이제 Notes List view 로 가 볼까요? 이제 New 버튼의 handler 부분을 다룰 차례입니다. 이 버튼이 눌려지면 새로운 note를 만들 수 있어야 합니다. 그러니까 이 버튼을 누르면 Note Editor를 화면에 보이도록 하면 되곘죠.

NotesApp.views.notesListToolbar = new Ext.Toolbar({
    id: 'notesListToolbar',
    title: 'My Notes',
    layout: 'hbox',
    items: [
        { xtype: 'spacer' },
        {
            id: 'newNoteButton',
            text: 'New',
            ui: 'action',
            handler: function () {

                var now = new Date();
                var noteId = now.getTime();
                var note = Ext.ModelMgr.create(
                    { id: noteId, date: now, title: '', narrative: '' },
                    'Note'
                );

                NotesApp.views.noteEditor.load(note);
                NotesApp.views.viewport.setActiveItem('noteEditor', {type: 'slide', direction: 'left'});
            }
        }
    ]
});

순서대로 한번 볼까요?
첫번째로 ModelMgr 클래스의 create()메소드를 사용해서 새로운 note를 생성합니다.

var now = new Date();
var noteId = now.getTime();
var note = Ext.ModelMgr.create(
    { id: noteId, date: now, title: '', narrative: '' },
    'Note'
);

그리고 나서 이 새 note를 Note Editor에 전해줍니다. FormPanel에서 이 부분이 보이도록 하기 위해 load 메소드를 사용했습니다. 이 load 메소드는 필드들을 보여줄겁니다. 이때 value 값들이 있으면 그 value 값들도 보여 줄 거구요.

NotesApp.views.noteEditor.load(note);

다음으로는 우리가 viewport에서 card layout을 사용했듯이 viewport이 setActiveItem()메소드를 사용해서 Note Editor를 보이도록 할 겁니다.
이 setActiveItem()을 call 하면 우리는 우리가 active 시키려고 하는 card의 id를 전달해 주고 그 객체가 transition 하는 animation 기능을 사용할 수 있습니다.

NotesApp.views.viewport.setActiveItem('noteEditor', {type: 'slide', direction: 'left'});

이 New 버튼이 어떻게 작동하는지 확인하기 전에 viewport의 items array를 약간 수정해야 합니다.

NotesApp.views.viewport = new Ext.Panel({
    fullscreen: true,
    layout: 'card',
    cardAnimation: 'slide',
    items: [
        NotesApp.views.notesListContainer,
        NotesApp.views.noteEditor
    ]
});



여기까지 완성 됐나요? 그러면 이제 user가 작성한 note를 save 할 수 있도록 하시면 됩니다.
이 기능은 당연히 Note Editor의 Save 버튼에 달아야 겠죠.

***** Validating a data model in Sencha Touch

save 버튼을 누르게 되면 우선 체크해야 할 것들이 몇가지 있습니다.

1. form field의 title과 narrative  정보는 Note Model 인스턴스에서 capture 됩니다.
2. note의 title의 value 가 없으면 유저에게 alert 화면을 띄울 겁니다.
3. note 가 new일 경우 이 note를 cache에 add 할 겁니다. 이 note 가 이전에 저장 됐던 것이면 cache에 있는 해당 note를 update 할 겁니다.
4. 그리고 나서 Notes List 를 refresh 해서 보여줄 겁니다.

자 이 기능들을 구현해 볼까요?
save 버튼의 tap 핸들러를 구현하기 전에 Note data model을 수정해서 validation 부분을 구현하는데 좀 더 편하도록 해 봅시다. 우리가 할 것은 model의 title 필드의 validation 함수를 사용해서 message 프로퍼티를 override 할 겁니다. 이 기능은 이 필드가 invalid 할 경우 메세지를 띄우는 기능입니다.

Ext.regModel('Note', {
    idProperty: 'id',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'date', type: 'date', dateFormat: 'c' },
        { name: 'title', type: 'string' },
        { name: 'narrative', type: 'string' }
    ],
    validations: [
        { type: 'presence', field: 'id' },
        { type: 'presence', field: 'title', message: 'Please enter a title for this note.' }
    ]
});

이 메세지는 우리가 Note Editor view 에서 note의 validation을 할 때 사용할 겁니다.
이제 save 버튼의 tap 핸들러를 구현해서 이 validation 이 어떻게 이뤄지는지 확인해 보겠습니다.

NotesApp.views.noteEditorTopToolbar = new Ext.Toolbar({
    title: 'Edit Note',
    items: [
        {
            text: 'Home',
            ui: 'back',
            handler: function () {
                NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });
            }
        },
        { xtype: 'spacer' },
        {
            text: 'Save',
            ui: 'action',
            handler: function () {

                var noteEditor = NotesApp.views.noteEditor;

                var currentNote = noteEditor.getRecord();
                // Update the note with the values in the form fields.
                noteEditor.updateRecord(currentNote);

                var errors = currentNote.validate();
                if (!errors.isValid()) {
                    currentNote.reject();
                    Ext.Msg.alert('Wait!', errors.getByField('title')[0].message, Ext.emptyFn);
                    return;
                }

                var notesList = NotesApp.views.notesList;
                var notesStore = notesList.getStore();

                if (notesStore.findRecord('id', currentNote.data.id) === null) {
                    notesStore.add(currentNote);
                } else {
                    currentNote.setDirty();
                }

                notesStore.sync();
  notesStore.sort([{ property: 'date', direction: 'DESC'}]);

                notesList.refresh();

                NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });

            }
        }
    ]
});

이 handler 함수에서 첫번째로 form panel의 getRecord() 메소드를 사용했습니다. 이 메소드는 form에 Note model이 로드되는 reference를 가질 수 있도록 해 줍니다. 그 다음에는 updateRecord() 메소드를 사용합니다. 이 메소드는 이 model reference로 폼 필드로부터 value들을 가져와서 전달해 줍니다.
validation dms Note data model에서 validate()를 call 함으로서 Errors 객체를 return 하도록 합니다. isValid()는 이 과정에서 에러가 있는지 없는지 알 수 있게 해 줍니다. 지난 시간에 했듯이 Note Editor 에서는 title 만이 not null입니다. 그래서 이 앱에서는 그 부분만 체크할 겁니다. 에러를 확인하기 위해서는 model의 validations config 옵션에서 정의했듯이 errors.getByField('title')[0] 메세지를 통해서 확인할 수 있습니다.

이 validation을 통화 하면 이 note를 cache에 add 해야 합니다. 대신 이 데이터가 이전에 있는지 확인하는 기능이 있어야 합니다.
아래 findRecord()메소드를 통해서 이 작업을 간단하게 해 주시구요.

var notesStore = notesList.getStore();
if (notesStore.findRecord('id', currentNote.data.id) === null) {
    notesStore.add(currentNote);
}


update 시키신 후에는 sync() 메소드를 이용해서 완전히 이 데이터를 저장하시면 됩니다. 오라클에서 commit; 기능하고 비슷합니다.
그 다음에 sort() 메소드를 사용해서 note를 날짜 순서로 정렬합니다. 그러면 notes list에 render 할 준비가 끝나는 겁니다.


notesList.refresh();

NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });

type을 보시면 slide와 right가 있을 겁니다. 이것은 화면 전환 할 때 된쪽에서 오른쪽으로 slide하게 화면이 바뀌도록 합니다.

이제 남은 것은 Home button에 handler를 구현하는 겁니다.
이 홈 버튼을 누르면 단순히 Notes List로 돌아가기만 하면 됩니다.

{
    text: 'Home',
    ui: 'back',
    handler: function () {
        NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });'s next
    }
}

한번 화면으로 테스트 해 보고 싶으신가요? 이제 실행 해 보시면 save하고 새 note를 create하는 것들이 다 가능할 겁니다.

***** What’s next
다음에 우리가 구현 할 것은 기존에 존재하는 notes를 수정하고 지우는 기능입니다.
이 기능은 다음 시간에 구현해 보겠습니다.

오늘까지 한 js 소스는 아래와 같습니다.

var App = new Ext.Application({
    name: 'NotesApp',
    useLoadMask: true,
    launch: function () {

        Ext.regModel('Note', {
            idProperty: 'id',
            fields: [
                { name: 'id', type: 'int' },
                { name: 'date', type: 'date', dateFormat: 'c' },
                { name: 'title', type: 'string' },
                { name: 'narrative', type: 'string' }
            ],
            validations: [
                { type: 'presence', field: 'id' },
                { type: 'presence', field: 'title', message: 'Please enter a title for this note.' }
            ]
        });

        Ext.regStore('NotesStore', {
            model: 'Note',
            sorters: [{
                property: 'date',
                direction: 'DESC'
            }],
            proxy: {
                type: 'localstorage',
                id: 'notes-app-store'
            }
        });

        NotesApp.views.noteEditorTopToolbar = new Ext.Toolbar({
            title: 'Edit Note',
            items: [
                {
                    text: 'Home',
                    ui: 'back',
                    handler: function () {
                        NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });
                    }
                },
                { xtype: 'spacer' },
                {
                    text: 'Save',
                    ui: 'action',
                    handler: function () {

                        var noteEditor = NotesApp.views.noteEditor;

                        var currentNote = noteEditor.getRecord();
                        // Update the note with the values in the form fields.
                        noteEditor.updateRecord(currentNote);

                        var errors = currentNote.validate();
                        if (!errors.isValid()) {
                            currentNote.reject();
                            Ext.Msg.alert('Wait!', errors.getByField('title')[0].message, Ext.emptyFn);
                            return;
                        }

                        var notesList = NotesApp.views.notesList;
                        var notesStore = notesList.getStore();

                        if (notesStore.findRecord('id', currentNote.data.id) === null) {
                            notesStore.add(currentNote);
                        } else {
                           currentNote.setDirty();
                        }

                        notesStore.sync();
                        notesStore.sort([{ property: 'date', direction: 'DESC'}]);

                        notesList.refresh();

                        NotesApp.views.viewport.setActiveItem('notesListContainer', { type: 'slide', direction: 'right' });

                    }
                }
            ]
        });

        NotesApp.views.noteEditorBottomToolbar = new Ext.Toolbar({
            dock: 'bottom',
            items: [
                { xtype: 'spacer' },
                {
                    iconCls: 'trash',
                    iconMask: true,
                    handler: function () {
                        // TODO: Delete current note.
                    }
                }
            ]
        });

        NotesApp.views.noteEditor = new Ext.form.FormPanel({
            id: 'noteEditor',
            items: [
                {
                    xtype: 'textfield',
                    name: 'title',
                    label: 'Title',
                    required: true
                },
                {
                    xtype: 'textareafield',
                    name: 'narrative',
                    label: 'Narrative'
                }
            ],
            dockedItems: [
                    NotesApp.views.noteEditorTopToolbar,
                    NotesApp.views.noteEditorBottomToolbar
                ]
        });

        NotesApp.views.notesList = new Ext.List({
            id: 'notesList',
            store: 'NotesStore',
            itemTpl: '
<div class="list-item-title">{title}</div>
' +
                '
<div class="list-item-narrative">{narrative}</div>
',
            onItemDisclosure: function (record) {
                // TODO: Render the selected note in the note editor.
            },
            listeners: {
                'render': function (thisComponent) {
                    thisComponent.getStore().load();
                }
            }
        });

        NotesApp.views.notesListToolbar = new Ext.Toolbar({
            id: 'notesListToolbar',
            title: 'My Notes',
            layout: 'hbox',
            items: [
                { xtype: 'spacer' },
                {
                    id: 'newNoteButton',
                    text: 'New',
                    ui: 'action',
                    handler: function () {

                        var now = new Date();
                        var noteId = now.getTime();
                        var note = Ext.ModelMgr.create(
                            { id: noteId, date: now, title: '', narrative: '' },
                            'Note'
                        );

                        NotesApp.views.noteEditor.load(note);
                        NotesApp.views.viewport.setActiveItem('noteEditor', { type: 'slide', direction: 'left' });
                    }
                }
            ]
        });

        NotesApp.views.notesListContainer = new Ext.Panel({
            id: 'notesListContainer',
            layout: 'fit',
            html: 'This is the notes list container',
            dockedItems: [NotesApp.views.notesListToolbar],
            items: [NotesApp.views.notesList]
        });

        NotesApp.views.viewport = new Ext.Panel({
            fullscreen: true,
            layout: 'card',
            cardAnimation: 'slide',
            items: [
                NotesApp.views.notesListContainer,
                NotesApp.views.noteEditor
            ]
        });
    }
});

이제 저도 Sencha Touch 에 대해 대충 감이 잡히네요.
다음시간에 첫번째 센차터치 앱 Notes 를 완료하겠습니다.
그리고 계속 하이브리드 모바일 앱을 위해 Corona SDK, HTML5, Sencha Touch, Phone Gap 등 관련 기술을 익히고 싶네요.

꾹~~ 꾹~~ 응원 부탁드려요... ~~~~~~~
반응형

Comment



Writing a Sencha Touch Application, Part 2

지난 시간에는 Sencha로 만드는 첫번째 앱인 My Notes 앱을 배웠습니다.
Notes List view를 말들고 있었습니다.
지난시간에 아래 화면까지 작업했습니다.



여기에 아래 mock-up 이미지처럼 툴바에 버튼을 달고 유저가 생성한 Notes들을 랜더링해서 보여주는 기능을 Ext.list를 이용해서 구현할 겁니다.



***** Creating a Data Model in Sencha Touch

우선 데이타 모델을 만들겠습니다. DB를 이용한다면 필드들을 만드는 겁니다.
리스트에 표시할 내용들에 대한 데이터 모델인데요 id,date,title,narrative 등이 있어야 합니다.
이 데이터 모델은 Ext.regModel() 메소드를 이용해서 만들겁니다.

Ext.regModel('Note', {
    idProperty: 'id',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'date', type: 'date', dateFormat: 'c' },
        { name: 'title', type: 'string' },
        { name: 'narrative', type: 'string' }
    ],
    validations: [
        { type: 'presence', field: 'id' },
        { type: 'presence', field: 'title' }
    ]
});

데이타 모델과 관련한 API는 여기를 클릭해서 보시면 도움이 될 겁니다.
Sencha Touch의 이 데이터 모델관련 메소드에서는 내부적으로 validation을 지원합니다.
위에는 id와 title에 validations를 주었습니다. 데이터가 꼭 있어야 된다는 내용입니다. sql로 치면 not null 입니다.
이 validation이 어떻게 동작하는지에 대해서는 나중에 살펴보도록 하죠.
또한 associations 기능도 지원을 하는데요 우리가 만드는 앱에서는 사용하지는 않습니다.
아주 유용한 기능이니까 API를 꼭 참조하세요.

***** Configuring a Sencha Touch Data Store to use HTML5 local storage

이제 데이터를 Cacheg하는 기능이 필요합니다. Ext.regstore() 함수가 데이터 store를 생성하도록 할 겁니다.
아래 소스코드를 참조하세요.

Ext.regStore('NotesStore', {
    model: 'Note',
    sorters: [{
        property: 'date',
        direction: 'DESC'
    }],
    proxy: {
        type: 'localstorage',
        id: 'notes-app-localstore'
    }
});

Ext.regStore() 는 프레임 워크의 Store Manager 와 같이 store를 생성하고 register 합니다. 프레임워크의 다른 클래스들 처럼 여러분은 앱의 데이터 store를 lookup 하고 modify 하는데 이 Store Manager를 사용할 수 있습니다.
우리의 NotesStore의 모델 config 옵션은 Note model 입니다. 우리는 또한 sorters 옵션도 사용해서 날짜 역순으로 표시할 겁니다.
우리의 앱은 브라우저 세션을 이용해서 notes를 저장할 수 있어야 합니다. 그러기 위해서는 store의 proxy로 모델데이터를 로드하고 저장하는 일을 해야 합니다. 그래서 proxy config 옵션을 사용합니다. 이 옵션을 사용함으로서 proxy 는 Ext.data.LocalStorageProxy 클래스의 인스턴스가 됩니다. 이 클래스는 HTML5의 LocalStorage API를 사용해 사용자 브라우저에 모델 데이터를 저장하게 됩니다.

***** Creating a Sencha Touch list

데이터 모델과 store 가 준비 됐으면 이제 notes list 를 생성할 수 있습니다.

NotesApp.views.notesList = new Ext.List({
    id: 'notesList',
    store: 'NotesStore',
    itemTpl: '
<div class="list-item-title">{title}</div>
' +
        '
<div class="list-item-narrative">{narrative}</div>
'
});

복잡한 거는 없습니다. store config 옵션에 이름을 넣습니다. render 하기 위해 itemTpi config 옵션을 사용합니다. 그 안에 있는 태그(markup)은 list-item-title과 list-item-narrative 클래스가 정의 돼 있습니다. 이 클래스는 app.css 파일에서 사용할 겁니다.

.list-item-title
{
    float:left;
    width:100%;
    font-size:90%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.list-item-narrative
{
    float:left;
    width:100%;
    color:#666666;
    font-size:80%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.x-item-selected .list-item-title
{
    color:#ffffff;
}
.x-item-selected .list-item-narrative
{
    color:#ffffff;
}

이제 panel의 items config 옵션을 사용해서 container panel에 list를 추가해 보겠습니다.

NotesApp.views.notesListContainer = new Ext.Panel({
    id: 'notesListContainer',
    layout: 'fit',
    html: 'This is the notes list container',
    dockedItems: [NotesApp.views.notesListToolbar],
    items: [NotesApp.views.notesList]
});

시뮬레이터에서 확인하기 전에 dummy note를 집어 넣겠습니다. 그래야 브라우저나 디바이스로 테스트하면 이 dummy 내용이 나올 테니까요. 아래와 같이 data config 옵션을 넣어 보세요.

Ext.regStore('NotesStore', {
    model: 'Note',
    sorters: [{
        property: 'date',
        direction: 'DESC'
    }],
    proxy: {
        type: 'localstorage',
        id: 'notes-app-store'
    },
    // TODO: remove this data after testing.
    data: [
        { id: 1, date: new Date(), title: 'Test Note', narrative: 'This is simply a test note' }
    ]
});

에뮬레이터에서 Notes List 는 아래와 같이 보일 겁니다.



이제 우리의 Notes List view는 거의 완성 됐습니다. 툴바를 만들었고 Note List도 만들었습니다. 그리고 data model,store도 구현했구요 이러한 것들은 이 notes를 cache 하게 될 겁니다. 아직 안된게 두개가 있습니다. 다른 페이지로 넘어가도록 하는 버튼들인데요. 툴바에 있는 New 버튼하고 각각의 List item에 있는 disclosure 버튼입니다.



***** Adding buttons to a Sencha Touch toolbar

아래 소스코드는 New 버튼을 툴바에 add 하는 방법을 보여줍니다.
NotesApp.views.notesListToolbar = new Ext.Toolbar({
    id: 'notesListToolbar',
    title: 'My Notes',
    layout: 'hbox',
    items: [
        { xtype: 'spacer' },
        {
            id: 'newNoteButton',
            text: 'New',
            ui: 'action',
            handler: function () {
                // TODO: Create a blank note and make the note editor visible.
            }
        }
    ]
});

보시면 툴바에 New button을 달 수 있도록 hbox 레이아웃과 spacer를 넣었습니다. 그리고 handler function 도 넣었습니다. 여기에는 나중에 Note Editor view 와 관련한 기능이 추가 될 겁니다.

***** Implementing disclosure buttons in a Sencha Touch list

각 리스트에 달릴 disclosure 버튼을 다는것도 쉽습니다. 아래 코드에서 보듯이 onItemDisclosure function을 사용하시면 됩니다.

NotesApp.views.notesList = new Ext.List({
    id: 'notesList',
    store: 'NotesStore',
    itemTpl: '
<div class="list-item-title">{title}</div>
' +
        '
<div class="list-item-narrative">{narrative}</div>
',
    onItemDisclosure: function (record) {
        // TODO: Render the selected note in the note editor.
    }
});

리스트 아이템에 tap event에 대한 listener를 달기 위해 onItemDisclsure를 override 하고 있습니다. 이 리스너가 하는 일은 유저가 리스트를 탭하면 이를 감지해서 Note Editor view에 알려주는 역할을 하게 될 겁니다.
이 기능은 Note Editor를 만들고 나서 나중에 구현하겠습니다.

***** Where are we?

여기까지 무사히 마쳤다면 아래와 같은 화면을 부실 수 있을 겁니다.



이제 어플리케이션의 main view를 완성했습니다. 두개의 이벤트 핸들러를 구현하는 부분은 남았지만 비쥬얼한 부분은 다 완성됐습니다.

이제 다음시간에는 Note Editor를 만들어 보겠습니다.



아래는 지금까지 한 소스 입니다.

var App = new Ext.Application({
    name: 'NotesApp',
    useLoadMask: true,
    launch: function () {

        Ext.regModel('Note', {
            idProperty: 'id',
            fields: [
                { name: 'id', type: 'int' },
                { name: 'date', type: 'date', dateFormat: 'c' },
                { name: 'title', type: 'string' },
                { name: 'narrative', type: 'string' }
            ],
            validations: [
                { type: 'presence', field: 'id' },
                { type: 'presence', field: 'title' }
            ]
        });

        Ext.regStore('NotesStore', {
            model: 'Note',
            sorters: [{
                property: 'date',
                direction: 'DESC'
            }],
            proxy: {
                type: 'localstorage',
                id: 'notes-app-localstore'
            },
            // TODO: remove this data after testing.
            data: [
                { id: 1, date: new Date(), title: 'Test Note', narrative: 'This is simply a test note' }
            ]
        });

        NotesApp.views.notesList = new Ext.List({
            id: 'notesList',
            store: 'NotesStore',
            itemTpl: '
<div class="list-item-title">{title}</div>
' +
                '
<div class="list-item-narrative">{narrative}</div>
',
            onItemDisclosure: function (record) {
                // TODO: Render the selected note in the note editor.
            }
        });

        NotesApp.views.notesListToolbar = new Ext.Toolbar({
            id: 'notesListToolbar',
            title: 'My Notes',
            layout: 'hbox',
            items: [
                { xtype: 'spacer' },
                {
                    id: 'newNoteButton',
                    text: 'New',
                    ui: 'action',
                    handler: function () {
                        // TODO: Create a blank note and make the note editor visible.
                    }
                }
            ]
        });

        NotesApp.views.notesListContainer = new Ext.Panel({
            id: 'notesListContainer',
            layout: 'fit',
            html: 'This is the notes list container',
            dockedItems: [NotesApp.views.notesListToolbar],
            items: [NotesApp.views.notesList]
        });

        NotesApp.views.viewport = new Ext.Panel({
            fullscreen: true,
            layout: 'card',
            cardAnimation: 'slide',
            items: [NotesApp.views.notesListContainer]
        });
    }
});

앞으로 두 번만 더 다루면 센차터치로 만드는 첫 번째 앱이 완성됩니다.
정말 기대가 되는데요.
다음 시간에 또 뵙구요... 꾹 꾹 추천 한방 눌러 주세요.... ~~~~
반응형

Comment

  1. 테일 2012.02.20 18:19

    감사히 보고 있습니다 ^^

    • 솔웅 2012.02.21 07:59 신고

      예 저도 감사합니다.
      질문이나 의견 있으시면 언제든지 말씀해 주세요.

      감사합니다.

  2. 우와 상세해 2012.03.21 15:55

    정말 감사합니다 많은 도움이 되고 있어요 ㅠ. ㅠ

    • 솔웅 2012.05.30 04:57 신고

      오래전에 댓글 올리셨네요. 이제야 확인합니다.
      저도 아주 감사드립니다.

  3. 1.x 기반소스인가요? 2.0.1에서는 정상작동을 안하네요?

    • 솔웅 2012.05.30 04:57 신고

      예 1.X 기반 소스예요. 써핑하다 보니까 1.x 대 소스만 있어서 일단 이것 가지고 개념이해하려고 정리했어요.
      2.0 대 소스는 잘 구하기 어려운것 같은데..
      어디 소스 있는데 알고 계시면 share 해 주세요. ^^
      감사합니다.


안녕하세요.
드디어 Sencha Touch로 앱을 만들기로 했습니다.
이번주 들어서 갑자기 HTML5로 게임 만들기하고 Sencha Touch 앱하고 본격적으로 공부하고 싶어지더라구요.

오늘은 첫번째 모바일 웹으로 간단한 Note 기능을 만들겠습니다.

이 앱의 기능은 유저가 Notes를 받아서 이것을 디바이스에 저장하고 앱을 시작하면 그 Notes들을 볼 수 있도록 하겠습니다.

이 앱을 만들기 위해서는 아래 작업들을 해야 합니다.
- Scencha Touch Application의 block들을 만든다.
- 리스트 뷰를 이용해 정보를 렌더링 한다.
- form elements들을 이용해서 정보를 editing 한다.
- 브라우저 세션을 이용해 클라이언트 사이드 data persistence를 구현한다.
- multi-view 어플리케이션으로 여러 화면을 navigation할 수 있도록 한다.


완성된 화면인데요.
New를 누르면 간단한 Note를 할 수 있는 화면이 나오고 위 화면은 앱을 켰을 때 그 Note들이 출력되도록 하는 List 화면입니다.

***** 어플리케이션 개요
- note를 생성할 수 도록 한다.
- 현재의 note를 수정할 수 있도록 한다.
- note를 delete 할 수 있도록 한다.
- 브라우저 세션을 이용해 어플리케이션이 동작하면서 device에 note를 저장할 수 있도록 한다.

이러한 기능들을 염두에 두고 비쥬얼한 디자인을 한번 보겠습니다.

***** 메인 뷰 디자인하기

우리가 첫번째로 만들어야 할 부분은 note를 수정할 수 있는 화면입니다.
이 화면은 form 을 이용해 만들겁니다. 앞으로 이 화면은 Note Editor라고 부르도록 하겠습니다.
대략 아래와 같이 될 겁니다.


이 Note Editor를 Sencha Touch components를 이용해서 어떻게 구현할까요?
아래 그림을 보세요.



또한 우리는 기존에 있던 note들을 리스트로 랜더링해서 보여주는 화면이 필요합니다.
이 화면이 아마 이 애플리케이션의 메인 화면이 될 겁니다.
또한 이 화면은 Note Editor와 연결 돼 있어야 합니다. 아래 대략적인 그림이 있습니다.



그리고 아래는 우리가 사용할 Sencha Touch components들 입니다.



이 두 화면 이외에 보이지는 않지만 이 앱에 꼭 필요한 component가 더 있습니다.
이 컴포넌트는 이 앱의 viewport와 같은 기능을 할거고 랜더링이나 Notes List와 Note Editor를 전환하는 부분을 담당하게 될 겁니다.
이 기능을 구현하기 위해 Notes List와 Note Editor가 layout's cards가 되는 Panel을 구성할 겁니다.



***** Sencha Touch application 의 block들 만들기

우리는 index.html, app.css, app.js 이렇게 세개의 파일을 만들겁니다.
index.html은 앱을 launch 하기 위한 파일입니다. 이 파일에는 기본 Sencha Touch framework와 우리가 사용할 app.js, app.js 파일들에 대한 정보가 들어 있습니다.

<!DOCTYPE html>
<html>
<head>
    <title>Getting Started</title>

<script src="sencha-touch-debug.js" type="text/javascript"></script>
<link href="sencha-touch.css" rel="stylesheet" type="text/css" />
<link href="app.css" rel="stylesheet" type="text/css" />
<script src="app.js" type="text/javascript"></script>
</head>
<body></body>
</html>



app.js와 app.css는 이 앱에서 사용할 자바스크립트와 css 파일입니다.

app.js에서 우리가 할 최초의 작업은 어플리케이션을 instantiate 하는 작업입니다.
var App = new Ext.Application({
    name : 'NotesApp',
    useLoadMask : true,
    launch : function () {
    }
})


Ext.Application 클래스는 Sencha Touch application 임을 말합니다.
자세한 사항은 http://docs.sencha.com/touch/1-1/#!/api/Ext.Application 에 있습니다.
새 application을 instantiate 하게 되면 자동적으로 전역번수 NotesApp이 생성되고 아래의 namespaces들이 만들어 집니다.
- NotesApp
- NotesApp.views
- NotesApp.models
- NotesApp.controllers
- NotesApp.stores

그리고 launch() 함수는 오직 한번만 실행됩니다. 여기에는 우리가 생성할 application의 view가 들어가게 됩니다.
launch: function () {

    NotesApp.views.viewport = new Ext.Panel({
        fullscreen: true,
        html:'This is the viewport'
    });
}


우리 앱의 viewport는 Ext.Panel 입니다. 이 panel에는 Notes List와 Note Editor가 그려지게 될 겁니다.
여기서 fullscreen config 옵션을 true로 하게 되면 이 panel이 브라우저의 모든 공간을 활용하게 됩니다.
여기에는 monitorOrientation config도 true로 할 수 있습니다. 이렇게 되면 모바일의 경우 orientation이 바뀌게 되면 화면도 바뀌게 됩니다.

여기까지 작업한 내용을 device나 simulator에서 돌리시면 아래와 같은 화면을 보실 수 있을겁니다.



***** Creating the Notes List container
Notes List는 앱이 실행될 때 유저에게 보여질 화면입니다. 아래 그림에서 보듯이 여기에는 툴바와 리스트가 있게 될 겁니다.
한번 구현해 보겠습니다.

첫번째로 우리는 툴바와 리스트를 display 하게 될 panel을 만들어야 합니다.



우리는 이 panel을 notesListContainer라고 부르겠습니다.
NotesApp.views.notesListContainer = new Ext.Panel({
    id : 'notesListContainer',
    layout : 'fit',
    html: 'This is the notes list container'
});


여기에 툴바와 리스트를 추가하기 전에 이 viewport안에서 rendering 작업을 해야 합니다.
var App = new Ext.Application({
    name: 'NotesApp',
    useLoadMask: true,
    launch: function () {

        NotesApp.views.notesListContainer = new Ext.Panel({
            id : 'notesListContainer',
            layout : 'fit',
            html: 'This is the notes list container'
        });

        NotesApp.views.viewport = new Ext.Panel({
            fullscreen : true,
            layout : 'card',
            cardAnimation : 'slide',
            items: [NotesApp.views.notesListContainer]
        });
    }
})


여기에 왜 card 레이아웃을 사용했을 까요? 왜냐하면 Notes List container와 Note Editor 들은 cards 들이기 때문입니다.
대부분의 모바일 앱이 그렇듯이 이 cards 들은 slide 애니메이션을 사용해서 display 될 겁니다.

이 소스를 device나 simulator에서 체크해 보시면 아래와 같은 화면을 보실 수 있을 겁니다.



뭐가 잘 못 된 걸까요? 툴바와 notes list가 안 보이네요. 이것들은 아래에서 마저 작업 하겠습니다.

***** Adding a Sencha Touch toolbar to a panel

아래와 같이 툴바를 정의할 수 있습니다. 여기에 버튼이 들어가야 되는데요 이건 나중에 작업하겠습니다.
NotesApp.views.notesListToolbar = new Ext.Toolbar({
    id: 'notesListToolbar',
    title: 'My Notes'
});


디바이스나 시뮬레이터로 아래처럼 화면이 출력되는지 확인해 보세요.



***** 다음 작업
오늘은 여기서 마치도록 하고요 다음 글에서는 방금 만든 notes list를 view에 추가하겠습니다. 그리고 note를 만들고 수정하는 기능들도 작업하겠습니다.

지금까지의 소스는 아래와 같습니다.

var App = new Ext.Application({
    name: 'NotesApp',
    useLoadMask: true,
    launch: function () {

        NotesApp.views.notesListToolbar = new Ext.Toolbar({
            id: 'notesListToolbar',
            title: 'My Notes'
        });

        NotesApp.views.notesListContainer = new Ext.Panel({
            id: 'notesListContainer',
            layout: 'fit',
            html: 'This is the notes list container',
            dockedItems: [NotesApp.views.notesListToolbar]
        });

        NotesApp.views.viewport = new Ext.Panel({
            fullscreen: true,
            layout: 'card',
            cardAnimation: 'slide',
            items: [NotesApp.views.notesListContainer]
        });
    }
})

지금까지의 소스는 아래 파일을 다운받아서 보시면 됩니다.



추천 추천 부탁드려요. ~~~~~~~ ~~~~~~~
반응형

Comment

  1. 그레인 트롤러 2012.04.11 22:02

    제이쿼리모바일을 써봤는데[
    이 이 글대로 센차 해봤는데 이야...
    역시 고급이네요.
    각 장단점으로
    센차는 어렵긴하네여, 제이큐리는 1일이면 뭐... 그냥 완성인데
    센차는 조금더 오래 해봐야할거같군요..
    자바스크립트...OTL

    • 솔웅 2012.04.12 06:12 신고

      그렇죠? JQuery Mobile은 갖다가 쓰기는 편한 것 같애요. 단지 가독성이 좀 떨어지는 것 같구요. 센차터치는 저도 좀 더 공부 해 봐야겠어요.
      감사합니다.

  2. 남의포스트 2012.05.09 22:42

    외국애가 만든 것을 자기 것인냥 적는 모습이 보기 좋지 않네요

    최소한 출처라도 적으심이..

    • 솔웅 2012.05.10 03:47 신고

      그렇군요.. 제가 쓴 것 같이 느껴지시나보네요.
      이 블로그의 Sencha Touch 를 비롯해서 Corona, HTML5 등 대부분의 예제들은 제가 공부하면서 본 예제 소스들입니다.
      그 Documents 들을 번역해서 올리는게 제일 큰 부분이구요. 가끔 원본 예제를 제가 나름대로 바꿔서 테스트해 보고 나름대로 이해한 걸 추가하기도 합니다.
      그런식으로 진행한다는 글은 이전에 계속 언급해와서 매번 글을 쓸때마다 넣지는 않아서 중간에 한 글을 보면 그렇게도 느낄 수 있겠네요.
      이글도 4번에 나눠서 올렸는데요. 4번째 글 보시면 그 예제대로 했는데 저는 잘 실행이 안되서 혹시 보시는 분들 중에 제대로 실행되시는 분 계시면 알려달라고 했습니다.
      그리고 훅스님이 본인은 잘 된다고 하시면서 선언 순서나 CSS 구현쪽을 보라고 조언도 주셨구요.
      대부분의 글에서는 원본 글에 대한 링크가 걸려 있습니다. 근데 이 글에는 없네요. 링크는 원래 글 다 작성되고 나서 따로 다는데 이날은 건너 뛰었나 봅니다. 저도 일 하면서 짬 내면서 하고 있어서 그땐 그 작업을 미처 하지 못할 상황이었나 봅니다.
      본문 내용은 대개 그 예제를 다룬 강좌를 번역한 것이라서 그 예제를 만든 사람이 쓴 글입니다. 그러니까 당연히 그 예제를 만든 사람이 쓴 글인것처럼 보이죠. 오해 않아시길 바랍니다.

    • 나그네 2013.03.26 00:12

      그냥 공부하며 지나가는 나그네인데요.. "남의포스트" 라고 글 적은분은 이 글에도 감성?! 이 느껴지나보네요.. 마치 "자기것인냥" 이라.. 피식 ..

  3. 만들어보고 싶은 IOS 애플리케이션이 있어서 센차를 공부하던 중 너무 자료가 없어서 막막했는데 정말 감사드립니다.
    하나씩 보면서 따라해보겠습니다.


Sencha Touch 를 설치하고 간단한 예제를 한번 실행해 보겠습니다.

일단 센차터치를 설치하기 위해서는 아래 3가지를 준비하셔야 합니다.
1. Sencha Touch SDK
    아래 페이지를 가시면 1.1.1과 2.0 developer preview 버전을 다운 받으 실 수 있습니다.
http://www.sencha.com/products/touch/download/
2. 웹서버
    저는 APM Setup 을 이용해서 아파치 웹 서버를 설치 했습니다.
    APM Setup download
3. 최신 웹 브라우저, 크롬, 사파리 추천

세가지 모두 준비 되셨으면 먼저 웹 서버부터 설치합니다.
그냥 클릭만 하면 됩니다.
다 설치 하신 후 크롬 브라우저를 여셔서 주소창에 localhost 를 칩니다.


이 화면이 나오면 웹서버 설치는 완료 된 것입니다.
잘 안되시면 아까 다운 받았던 홈페이지를 참조하세요.

그 다음엔 다운받았던 센차터치 SDK 압축을 풉니다.
그리고 그 폴더를 웹서버의 htdocs 폴더에 복사해 넣습니다.
C:\APM_Setup\htdocs (디폴트로 깔면 경로가 이렇습니다.)

복사가 완료 되면 크롬 브라우저를 열어서 주소창에 http://localhost/sencha-touch-2-pr2 를 입력하고 엽니다.


이렇게 화면이 나오면 설치가 완료 된 겁니다.

이제 예제를 한번 실행해 볼까요?

먼저 아무곳에나 폴더 하나를 만드시고 아래와 같이 index.html을 만드세요.
<!DOCTYPE html>
<html>
<head>
    <title>Getting Started</title>
    <link rel="stylesheet" href="sencha-touch.css" type="text/css">
    <script type="text/javascript" src="sencha-touch-all.js"></script>
    <script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>

그리고 센차터치가 깔려 있는 폴더의 아래 파일을 복사해서 index.html이 있는 폴더에 넣습니다.
resources/css/sencha-touch.css
그리고 센차터치폴더에 있는 sencha-touch-all.js 파일도 복사해 넣습니다.

이러면 센차터치를 이용할 준비가 끝난겁니다.

이제 한번 이용해 볼까요?
아래와 같이 app.js를 index.html 이 있는 폴더에 만듭니다.
Ext.application({
    name: 'Sencha',

    launch: function() {
        alert('launched');
    }
});
그리고 크롬에서 이 index.html을 불러옵니다.

이렇게 나오면 센차터치로 첫번째 프로그램을 만든 겁니다.
그럼 이제 크롬에서 다시 http://localhost/sencha-touch-2-pr2 로 가 보겠습니다.

여기서 Get Started with 2.0 에 있는 Read the guide를 클릭해 보세요.

스크롤을 내리다 보면 위 화면이 보일겁니다. 여기서 Live Preview 를 클릭해 보세요.


그러면 이렇게 크롬 브라우저에서 시뮬레이터가 뜨면서 결과가 출력 됩니다.

그 아래 예제 하나만 더 해 볼까요?
Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.TabPanel", {
            fullscreen: true,
            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    html: 'Welcome'
                }
            ]
        });
    }
});

위 코드를 아까 만들었던 app.js 파일에 덮어 쓰고 저장하세요.

크롬에서 실행하면 이런 화면이 나옵니다.
그럼 아까 웹서버로 불러왔던 getting started 화면에서 Live Preview를 클릭해 보겠습니다.


같은 화면이 시뮬레이터에서 나오죠?

그 아래에 있는 예제들도 해 보세요.

오늘은 센차터치 설치하고 예제를 웹서버를 통해 시뮬레이터로 보는 방법과 웹서버가 아닌 그냥 브라우저로 보는 방법을 배웠습니다.

다음엔 본격적인 센차터치 공부를 할 텐데요. 오늘 getting started 에 나와있는 예제를 잘 보시면 대충 문법은 이해가 가실겁니다.

다음시간부터 자세히 다뤄 볼께요.


반응형

Comment

  1. bmw2040 2012.04.05 17:25

    하이브리드앱 관련해서 공부중에 있습니다. 위에 예제를 보고 실행을 해보려고
    하는데 문제접이 생겨서 코멘트를 달게 되었습니다. 현재 웹서버는 설치 완료
    한 상태이고 Sencha Touch SDK 를 1.1.1 버전으로 다운받아서 htdocs 폴더에
    복사를 했습니다. 그리고 위에 주소대로 쳐보면 not found 라고 나오는데 따로
    설정을 해주어야 하는게 있나요? 아니면 제가 잘못 다운을 받은 건가요;

    • 솔웅 2012.04.05 18:05 신고

      따로 설정하는건 아니고 htdocs 밑에 넣었으면 경로만 넣으면 됩니다. index.html 이 있는 폴더까지 경로를 넣으면 되거든요.
      제 경우는 아래처럼 하면 나와요.
      http://localhost/sencha-touch-2-pr2/
      bmw2040님은 어떻게 경로를 넣으셨는지요.
      그냥 localhost 만 치면 기본 화면은 나오나요?

Sencha Touch Road Show 를 다녀와서....

2011. 12. 13. 16:02 | Posted by 솔웅


안녕하세요?

오늘은 맨하튼에서 있었던 Sencha Touch Road Show를 다녀왔습니다.
9시30분부터 1시 30분까지 4시간 동안 진행 됐는데요.

중간에 샌드위치 스낵 커피 음료 등을 마음껏 먹을 수 있어서 좋았어요.
강의가 3개 있었는데 일반적인 HTML5 관련한 강의와 Sencha Touch 전반적인 사항 그리고 개발자가 나와서 예제 프로그램 설명하는 시간을 가졌었습니다.

자세히 필기하지 않아서 꼼꼼하게 정리는 못하지만 그나마 생각나는것들은 정리해 두는게 나중에라도 참고할 수 있고 더 좋을 것 같네요.

sencha 회사 홈페이지는 http://www.sencha.com/ 입니다.
products - sencha touch 메뉴로 가면 sencha touch를 다운 받을 수 있는데요.
지금은 1.0 버전과 1.1.1 버전이 다운 가능합니다.

이번에 참가자들에게 아직 공개 되지 않은 sencha touch 2.0 을 소개해 줬습니다.
위에 링크를 따라 가시면 다운 받으실 수 있을 겁니다.

그리고 조만간 Sencha Designer 도 개발 할 예정이라고 합니다.
Sencha Designer는 드림위버나 비쥬얼 베이직 같이 쉽게 개발할 수 있는 툴입니다.
Sencha 는 ExtJS 도 만들어 낸 회사인데요. 이미 ExtJS는 Ext Designer 가 나와 있습니다.

Sencha Designer가 궁금하시면 이 Ext Designer를 보시면 될겁니다. 같은 회사인데 비슷한 UI 일것 같네요.

오늘은 한 50여명이 참가했는데요. 강의마다 질문들이 꼬리를 이어서 이곳 개발자들의 열정을 느낄 수 있더라구요.

HTML- JAVA Script 관련 디버깅 툴을 누군가가 질문을 했는데 개발자가 Phantom JS 가 좋은 것 같다면서 추천해 주더라구요.
관심 있으신 분들은 가서 살펴 보세요.

예제를 다뤄준 마지막 강좌 파워포인트는 아래 올려 놓을 께요.


yelp.com 이란 곳에서 샌프란시스코의 store 정보를 얻어와서 보여주는 웹앱입니다.
그 contents는 한국에서는 별로 쓸모가 없었지만 개발 소스나 방법등을 배우기에는 좋을 것 같습니다.

앞으로 Corona SDK 와 HTML 5 , Sencha Touch 로 이 블로그를 채워 나갈 것 같습니다.
그리고 추가한다면 Phonegap이 있을 수 있겠구요.
좀 바쁘겠네요..

컨퍼런스가 증권거래소 근처에서 열렸었거든요.
끝나고 나오니까 증권거래소 앞 크리스마스 트리가 멋있게 서 있어서 한 카트 찍었습니다.

질문이나 의견 제안 어떤 것이든 댓글 달아 주세요. 저도 배우는 과정이니까 같이 알아보면 서로 도움이 될 것 같아요..

그럼..
반응형

Comment

  1. 사진을 두개 올렸는데 안 나타나네요..
    왜 그럴까?
    다른 분들도 안 나오나요?

  2. 지나가는 사람 2011.12.15 18:33

    사진 두 개 다 보이네요. 잘 보고 갑니다.

  3. 오우 2012.01.08 04:01

    잘 보고 갑니다~

이전 1 2 3 다음