역할
모델을 감쌈
데이터 로딩 및 저장하는 프록시 설정
정렬, 필터링, 그룹핑의 추가 기능
리더 클래스(Reader Class)
서버로부터 모델 인스턴스나 스토어를 로딩할 때 원본 데이터의 디코딩을 담당
모델을 감쌈
데이터 로딩 및 저장하는 프록시 설정
정렬, 필터링, 그룹핑의 추가 기능
서버로부터 모델 인스턴스나 스토어를 로딩할 때 원본 데이터의 디코딩을 담당
데이터의 로딩 및 저장
로컬 저장소에 사용. 브라우저를 종료하고 다시 열었을 때도 값이 저장되어 있음.
html5의 새로운 기능. 일부 브라우저만 지원
//로컬 스토리지 정의 Ext.define('UserPreference', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'description', type: 'string'} ], proxy: { type: 'localstorage', id: 'userpreference' } }); //생성 var store = Ext.create('Ext.data.Store', { model: 'UserPreference' }); //로드 및 데이터 저장 store.load(); store.add({description: 'Blue theme'}); store.add({description: 'Loiane Groner'}); store.sync(); //모델의 데이터 직접 관리 가능 var userPref = Ext.ModelManager.create({ description: 'Favorite JS Framework: extjs' }, 'UserPreference'); userPref.save(); //브라우저를 닫고 다시 열었을 때 데이터 로드 store.load(functin(records, operation, success){ var userPref, i; for(i=0; i<records.length; i++) { userPref = records[i].data; console.log(userPref.id + " " + userPref.description); } });
Ext.define('UserPreference', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'description', type: 'string'} ], proxy: { type: 'sessionstorage', id: 'userpreference' } }); var store = Ext.create('Ext.data.Store', { model: 'UserPrefeence' }); store.load(); store.add({description: 'Blue thene'}); store.add({description: 'Loiane Groner'}); store.sync();
안라인 데이터 로딩할 때 주로 사용하는 헬퍼 프록시. 페이지가 초기화될 때 포함된 모든 내용을 잃어버리므로, 임시 페이지에 유용.
Ext.define({ extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'} ], }); var data= { genders: [{ id: 1, name: 'Femail' }, { id: 2, name: 'Male' }, { id: 3, name: 'Unknown' }] }; var store = Ext.create('Ext.data.Store', { authoLoad: true, model: 'Gender', data: data, proxy: { type: 'memory', reader: { type: 'json', root: 'genders' } }, }); //데이터 스토어를 사용하는 콤보박스 생성 var comboBox = Ext.create('Ext.form.field.ComboBox', { fieldLabel: 'Gender', renderTo: 'genderCombo', displayField: 'name', width: 200, labelWidth: 50, store: store, queryMode: 'local', typeAhead: false });
웹 서버로부터 http 요청으로 데이터를 로딩하거나 저장할 때 사용.
//모델 설정 Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'title', type: 'string'}, {name: 'pages', type: 'int'} ], proxy: { type: 'ajax', url: 'data/books.json' } }); //동일한 다른 코드 var ajaxProxy = Ext.create('Ext.data.proxy.Ajax', { url:'data/book.json', model: 'Book', render: 'json' }); Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'title', type: 'string'}, {name: 'pages', type: 'int'} ], proxy: ajaxProxy }); //스토어 생성, 데이터 로딩 후 리스트 출력 var store = Ext.create('Ext.data.Store', { model: 'Book' }); store.load(function(records){ var book, i; for(i=0; i<records.length; i++){ book = records[i].data; console.log(book.id+" "+book.title); } });
파라미터 옵션
프록시의 읽기 또는 쓰기 동작 때 실행되는 클래스.
operation 옵션
filters, group, limit, sorters, start는 읽기 요청에만 사용 가능
//book 5개 로딩 var operation = Ext.create('Ext.data.Operation', { action: 'read', startParam: 'firstRecord', start: 0, limit: 5 }); proxy.read(operation); //특정 페이지를 로딩 + 정렬 설정 var operation = Ext.create('Ext.data.Operation', { action: 'read', page: 5, sorters: [ Ext.create('Ext.util.Sorter', { property: 'pages', direction: 'DESC' }); ] }); proxy.read(operation);
프록시가 만드는 URL 요청 : 1) /books?firstRecord=0&limit=5 2) /books?page=5
요청 URL의 가독성을 위한 코드 수정
var proxy = Ext.create('Ext.data.proxy.Ajax', { url: '/books', model: 'Book', encodeSorters: function(sorters) { var length = sorters.length; var sortStrs = []; var sorter, i; for(i=0 ; i<length; i++) { sorter = sorters[i]; sortStrs[i] = sorter.property+','+sorter.direction; } return sortStrs.join(";"); }, encodeFilters: function(filters) { var length = filters.length; var filterStrs = []; var filter, i; for(i=0; i<length ; i++) { filter = filters[i]; filterStrs[i] = filter.property+','+filter.value; } return filterStrs.join(";"); } });
애플리케이션이 배포된 도메인과 같은 도메인의 URL만 호출이 가능함. 다른 서버로 Ajax 호출을 만들 수 없음.
AjaxProxy의 서브클래스. 모든 CRUD 동작을 REST 형식으로 만듦.
(CRUD : Create, Read, Update, Delete)
다른 서버로 Ajax 호출을 만들 수 없음.
애플리케이션이 배포되어 있는 도메인과 다른 도메인의 요청을 만들 수 있음
//추가되는 태그 <script src="http://mydomain/url?callback=someCallback" /> Ext.define('Blog', { extend: 'Ext.data.Model', fields: [ {name: 'lang', type: 'string'}, {name: 'url', type: 'string'} ], type: 'jsonp', url: 'http://requestdomain.com/test/test.php' }); var store = Ext.create('Ext.data.Store', { model: 'Blog' }); store.load(function(records) { var blog, i; for(i=0; i<records.length; i++) { blog = records[i].data; console.log(blog.id+":"+blog.url); } });
Ext.define('Patient', { extend: 'Ext.data.Mode', fields: [ {name: 'name'}, {name: 'age', type: 'int'}, {name: 'phone', type: 'string'}, {name: 'weight', type: 'float'}, {name: 'weightKg', type: 'float', convert: function(value, record) { var weghtPounds = record.get('weight'); return Math.round(weightPounds * 0.45359237); } } ] });
var patient = Ext.craete('Patient', { name: 'Loiane Groner', age: 25, gender: 'F', phone:'9876-5432', weight:150 });
var patient = Ext.ModelMgr.create({ name:'Loiane Groner', age: 25, gender:'F', phone: '9876-5432', weight:150 }, 'Patient');
로딩과 저장을 모델로부터 직접 수행할 수 있으므로 스토어 클래스가 필요 없음.
patient.get('name'); patient.get('weightKg');
Ext.define('Patient', { extend: 'Ext.data.Mode', fields: [ ... ], validation: [ {type: 'presence', field: 'age'}, {type: 'length', field: 'name', min:2, max:60}, {type: 'format', field: 'name', matcher: /([a-z ]+)/}, {type: 'inclusion', field: 'gender', list:['M', 'F']}, {type: 'exclusion', field: 'weight', list:[0]} ] });
var errors = patient.validate(); errors.isValid(); //유효한 경우 true, 유효하지 않으면 false 리턴 errors.items; //모든 에러 목록 리턴 errors.getByField('name'); //name 필드에 대한 에러 확인
Ext.define('Blog', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'url', type: 'string'} ], proxy: { type: 'rest', url: 'data/blogs', format: 'json', reader: { type: 'json', root: 'blogs' } } });
프록시 정보 재사용
var store = Ext.create('Ext.data.Store', { model: 'Blog' }); store.load(function(record){ Ext.MessageBox.alert('Testing extjs 4 Models', "Loaded " + store.getCount() + " records"); });
스토어 내부에서 프록시 선언
Ext.define('Blog', { extend: 'Ext.data.Model', fields:[ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'url', type: 'string'} ] });
Blog.load(1, { //1 : 아이디 success: function(blog) { console.log("blog: " + blog.get('url')); } }); var store = Ext.create('Ext.data.Store', { model: 'blog', proxy: { type: 'rest', url: 'data/blogs', format: 'json', reader: { type: 'json', root: 'blogs' } } });
blog.set('name', 'Loiane'); blog.save({ success: function() { console.log('The blog was updated'); } });
blog.destroy({ success:function() { console.log('The blog was destroyed!'); } });
var blog = Ext.create({ name: 'Loiane Groner - Pt_BR', url: 'http://loiane.com' }, 'Blog'); blog.save();
새로 만든 blog의 아이디는 data/blogs에 POST요청을 보내고 응답으로 받는다.
{ "id": 2, "name": 'Loiane Groner - Pt_BR', "url": 'http://loiane.com' }
Ext.define('Author',{ extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'} ], hasMany: {model: 'Book', foreignKey: 'authorId'} //default primaryKey : Author.id, foreignKey : author_id }); Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'title', type: 'string'}, {name: 'pages', type: 'int'}, {name: 'numChapters', type: 'int'}, {name: 'authorId', type: 'int'} ], hasMany: {model: 'Chapter', foreignKey: 'bookId'} //default primaryKey : Book.id, foreignKey default: book_id }); Ext.define('Chapter', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'number', type: 'int'}, {name: 'title', type: 'string'}, {name: 'bookId', type: 'int'} ] });
hasMany 관계 옵션
Author.load(1, { //id가 1인 작가 정보 호출 success: function(author){ var books = author.books();// author의 id와 같은 값의 authorId를 가지고 있는 모든 book 리턴 console.log("Author " + author.get('name') + " has written " + books.getCount() + " books"); books.each(function(book){ var title = book.get('title'); var chapters = book.chapters(); console.log("Book " + title + " has " + chapters.getCount() + " chapters"); chapters.each(function(chapter){ console.log(chapter.get('number') + " " + chapter.get('title')); }); }); } });
필터를 적용할 경우
hasMany: {model: 'Book', foreignKey: 'authorId', filterProperty: 'filter'} var store = Ext.create('Author', {filter: 'Loiane Groner'}).books(); var store = Ext.create('Ext.data.Store', { model: 'Book', filters: [ { property: 'filter', value: 'Loiane Groner' } ] });
var author = Ext.ModelMgr.create({ id: 2, name: 'Loiane Groner' }, 'Author'); //Author 객체 생성 var books = author.books(); book.add({ title: 'extjs 4 : First Look', pages: 250, numChapters: 7 }); //새로운 book 객체 추가 books.sync(); // 추가된 book을 author에 추가
Ext.define('Author', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'} ], hasMany: {model: 'Book', foreignKey: 'authorId'} }); Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'pages', type: 'int'}, {name: 'numChapters', type: 'int'}, {name: 'authorId', type: 'int'} ], hasMany: {model: 'Chapter', foreignKey: 'bookId'}, belongsTo: {model: 'Author', foreignKey: 'authorId'} }); Ext.define('Chapter'{ extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'number', type: 'int'}, {name: 'title', type: 'string'}, {name: bookId', type: 'int'} ], belogsTo: {model: 'Book', foreignKey: 'bookId'} });
belongsTo 관계 옵션
Book.load(11, { success: function(book) { book.getAuthor(function (author) { //Author 객체에 설정된 프록시를 사용해 데이터 로딩. console.log("The author of this book is " + author.get('name')); callback: function(author, operation) {}, //book.getAuthor() 호출 시 사용. 항상 호출. success: function(author, operation) {}, //데이터 로딩 성공 시 호출 faliure: function(author, operation) {}, //데이터 로딩 실패 시 호출 scope: this //option. 함수들이 실행될 때 범위 지정. }); } });
getter, setter 함수 사용
book.setAuthor(1); book.set('authorId', 1); //둘이 동일함. book.setAuthor(1, function(book. operation) { console.log(book.get('authorId')); //1 출력 }); book.setAuthor(1, { callback: function(book, operation) {}, success: function(book, operation) {}, failure: function(book, operation) {}, scope: this });
Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'title', type: 'string'}, {name: 'pages', type: 'int'}, {name: 'numChapters', type: 'int'}, {name: 'authorId', type: 'int'} ], associations: [ {type: 'hasMany', model: 'Chapter', foreignKey: 'bookId'}, {type: 'belongsTo', model: 'Author', foreignKey: 'authorId'} ] });