Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / data / associations.js
1 Ext.require([
2     'Ext.data.*',
3     'Ext.panel.Panel',
4     'Ext.layout.container.Card',
5     'Ext.tip.QuickTipManager'
6 ]);
7
8 Ext.define('Customer', {
9     extend: 'Ext.data.Model',
10     fields: [{
11         name: 'id',
12         type: 'int'
13     }, 'name', 'phone'],
14     associations: [{
15         model: 'Order',
16         type: 'hasMany',
17         autoLoad: true
18     }],
19     proxy: {
20         type: 'ajax',
21         url: 'customer.php'
22     }
23 });
24
25 Ext.define('Order', {
26     extend: 'Ext.data.Model',
27     fields: [{
28         name: 'id',
29         type: 'int'
30     },{
31         name: 'customer_id',
32         type: 'int'
33     },{
34         name: 'date',
35         type: 'date',
36         dateFormat: 'Y-m-d'
37     }],
38     belongsTo: 'Customer',
39     associations: [{
40         model: 'OrderItem',
41         type: 'hasMany',
42         autoLoad: true
43     }],
44     proxy: {
45         type: 'ajax',
46         url: 'order.php'
47     }
48 });
49
50 Ext.define('OrderItem', {
51     extend: 'Ext.data.Model',
52     fields: [{
53         name: 'id',
54         type: 'int'
55     }, {
56         name: 'order_id',
57         type: 'int'
58     },'product', {
59         name: 'quantity',
60         type: 'int'
61     }, {
62         name: 'price',
63         type: 'float'
64     }],
65     belongsTo: 'Order',
66     proxy: {
67         type: 'ajax',
68         url: 'orderitem.php'
69     }
70 });
71
72 Ext.define('CustomerGrid', {
73     extend: 'Ext.grid.Panel',
74     alias: 'widget.customergrid',
75     
76     title: 'Customers',
77     
78     initComponent: function(){
79         Ext.apply(this, {
80             store: {
81                 autoLoad: true,
82                 model: 'Customer',
83                 listeners: {
84                     load: function() {
85                         Logger.log('Customer store loaded', false);
86                     }
87                 }
88             },
89             columns: [{
90                 text: 'Id',
91                 dataIndex: 'id'
92             },{
93                 text: 'Name',
94                 dataIndex: 'name',
95                 flex: 1
96             }, {
97                 text: 'Phone',
98                 dataIndex: 'phone'
99             }],
100             dockedItems: [{
101                 xtype: 'toolbar',
102                 items: {
103                     itemId: 'load',
104                     text: 'Load Orders',
105                     scope: this,
106                     handler: this.loadOrders,
107                     disabled: true
108                 }
109             }]
110         });
111         this.callParent();
112         this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
113     },
114     
115     onSelectChange: function(selModel, selections) {
116         this.active = selections[0];
117         this.down('#load').setDisabled(!this.active);
118     },
119     
120     loadOrders: function(){
121         var rec = this.active,
122             name = rec.get('name'),
123             owner = this.ownerCt,
124             orders;
125          
126         
127         orders = rec.orders();
128         if (orders.isLoading()) {
129             Logger.log('Begin loading orders: ' + rec.getId(), true);
130         }
131         orders.on('load', function(){
132             Logger.log('Order store loaded - ' + rec.getId(), false);
133         });
134         owner.add({
135             title: 'Orders - ' + rec.getId(),
136             customer: rec,
137             xtype: 'ordergrid',
138             store: orders
139         });
140         owner.getLayout().next();
141     }    
142 });
143
144 Ext.define('OrderGrid', {
145     extend: 'Ext.grid.Panel',
146     alias: 'widget.ordergrid',
147     
148     initComponent: function(){
149         Ext.apply(this, {
150             columns: [{
151                 text: 'Id',
152                 dataIndex: 'id'
153             },{
154                 flex: 1,
155                 text: 'Date',
156                 dataIndex: 'date',
157                 renderer: Ext.util.Format.dateRenderer('Y-m-d')
158             }],
159             dockedItems: [{
160                 xtype: 'toolbar',
161                 items: [{
162                     text: 'Back',
163                     scope: this,
164                     handler: this.onBackClick
165                 },{
166                     itemId: 'load',
167                     text: 'Load Order Items',
168                     scope: this,
169                     handler: this.loadItems,
170                     disabled: true
171                 }]
172             }]
173         });
174         this.callParent();
175         this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
176     },
177     
178     onBackClick: function(){
179         this.ownerCt.getLayout().prev();
180         this.destroy();    
181     },
182     
183     onSelectChange: function(selModel, selections) {
184         this.active = selections[0];
185         this.down('#load').setDisabled(!this.active);
186     },
187     
188     loadItems: function(){
189         var customerName = this.customer.get('name'),
190             rec = this.active,
191             date = Ext.Date.format(rec.get('date'), 'Y-m-d'),
192             owner = this.ownerCt,
193             orderitems;
194         
195         orderitems = rec.orderitems();
196         if (orderitems.isLoading()) {
197             Logger.log('Begin loading order items - ' + rec.getId(), true);
198         }
199         orderitems.on('load', function(){
200             Logger.log('Order items loaded - ' + rec.getId(), false);
201         });
202         owner.add({
203             title: 'Order Items - ' + rec.getId(),
204             xtype: 'orderitemgrid',
205             store: orderitems
206         });
207         owner.getLayout().next();
208     }    
209 });
210
211 Ext.define('OrderItemGrid', {
212     extend: 'Ext.grid.Panel',
213     alias: 'widget.orderitemgrid',
214     
215     initComponent: function(){
216         Ext.apply(this, {
217             columns: [{
218                 text: 'Id',
219                 dataIndex: 'id'
220             },{
221                 flex: 1,
222                 text: 'Product',
223                 dataIndex: 'product'
224             }, {
225                 text: 'Quantity',
226                 dataIndex: 'quantity'
227             }, {
228                 text: 'Price',
229                 dataIndex: 'price',
230                 renderer: Ext.util.Format.usMoney
231             }],
232             dockedItems: [{
233                 xtype: 'toolbar',
234                 items: [{
235                     text: 'Back',
236                     scope: this,
237                     handler: this.onBackClick
238                 }, {
239                     itemId: 'load',
240                     text: 'Parent association loader',
241                     tooltip: 'Demonstrate loading parent relationships - A new record will be created so we ignore any previous associations setup',
242                     scope: this,
243                     handler: this.onLoadClick,
244                     disabled: true
245                 }]
246             }]
247         });
248         this.callParent();
249         this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
250     },
251     
252     onSelectChange: function(selModel, selections) {
253         this.active = selections[0];
254         this.down('#load').setDisabled(!this.active);
255     },
256     
257     onBackClick: function(){
258         this.ownerCt.getLayout().prev();
259         this.destroy();    
260     },
261     
262     onLoadClick: function(){
263         var rec = this.active,
264             id = rec.getId();
265         
266         new ItemLoader({
267             width: 400,
268             height: 400,
269             modal: true,
270             title: this.title.replace('Order Items', 'Order Item ' + id),
271             orderItemData: rec.data,
272             orderItemId: id
273         }).show();
274     }
275 });
276
277 Ext.define('ItemLoader', {
278     extend: 'Ext.window.Window',
279     
280     initComponent: function(){
281         Ext.apply(this, {
282             border: false,
283             dockedItems: [{
284                 xtype: 'toolbar',
285                 items: [{
286                     text: 'Print order detail',
287                     scope: this,
288                     handler: this.onOrderClick
289                 }, {
290                     itemId: 'company',
291                     text: 'Print company detail',
292                     disabled: true,
293                     scope: this,
294                     handler: this.onCompanyClick
295                 }]
296             }],
297             bodyPadding: 5,
298             tpl: '<div>{type} {id} - {value}</div>',
299             tplWriteMode: 'append'
300         });
301         this.callParent();
302         this.orderItem = new OrderItem(this.orderItemData, this.orderItemId);
303     },
304     
305     onOrderClick: function(){
306         var id = this.orderItem.get('order_id'),
307             hasOrder = !!this.order;
308             
309         if (!hasOrder) {
310             Logger.log('Begin loading order - ' + id, true);
311         }
312         this.orderItem.getOrder({
313             scope: this,
314             success: function(order){
315                 this.order = order;
316                 this.down('#company').enable();
317                 if (!hasOrder) {
318                     Logger.log('Order loaded - ' + id, false);
319                 }
320                 this.update({
321                     type: 'Order',
322                     id: order.getId(),
323                     value: Ext.Date.format(order.get('date'), 'Y-m-d')
324                 });
325             }
326         });
327     },
328     
329     onCompanyClick: function(){
330         var id = this.order.get('customer_id'),
331             hasCustomer = !!this.customer;
332             
333         if (!hasCustomer) {
334             Logger.log('Begin loading customer - ' + id, true);
335         }
336         this.order.getCustomer({
337             scope: this,
338             success: function(customer){
339                 this.customer = customer;
340                 if (!hasCustomer) {
341                     Logger.log('Customer loaded - ' + id, false);
342                 }
343                 this.update({
344                     type: 'Customer',
345                     id: customer.getId(),
346                     value: customer.get('name')
347                 });
348             }
349         });
350     }    
351 });
352
353 Logger = (function(){
354     var panel;
355     
356     return {
357         init: function(log){
358             panel = log;
359         },
360         
361         log: function(msg, isStart){
362             panel.update({
363                 now: new Date(),
364                 cls: isStart ? 'beforeload' : 'afterload',
365                 msg: msg
366             });
367             panel.body.scroll('b', 100000, true);
368         }    
369     };
370 })();
371
372 Ext.onReady(function(){
373     
374     var main = Ext.create('Ext.panel.Panel', {
375         renderTo: document.body,
376         width: 750,
377         height: 400,
378         border: false,
379         layout: {
380             type: 'vbox',
381             align: 'stretch'
382         },
383         items: [{
384             height: 200,
385             xtype: 'container',
386             layout: 'card',
387             margin: '0 0 5 0'
388         }, {
389             flex: 1,
390             title: 'Loader log',
391             tplWriteMode: 'append',
392             tpl: '<div class="{cls}">[{now:date("H:i:s")}] - {msg}</div>',
393             bodyPadding: 5,
394             autoScroll: true,
395             listeners: {
396                 render: Logger.init
397             }
398         }]
399     });
400     Logger.log('Begin loading customer store', true);
401     main.items.first().add({
402         xtype: 'customergrid'
403     });
404     
405 });