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