We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 14951
    • 151 Posts
    Once again, ExtJs has me stuck. I'm learning leaps and bounds but every once and a while I'm still hitting a dead end.

    This time, my issue resides in the MODx Window Formpanel. Here is what I have..

    - A grid which displays a list of orders from my custom db tables (Pretty simple..All good)
    - A window used to update the selected record from the grid. (Again...All good)
    - A button which opens an additional window with a few of the form fields of the same record. (Mostly good..)

    The secondary window (which opens when the button is clicked) is successfully filled with proper record details... All seems to be well. Upon clicking save the form correctly POST's to the connector, and receives a successful response (as seen in firebug), the database record is in-fact updated...BUT... The window stays open and gives the javascript error:
    TypeError: m.fireFn.apply is not a function - ext-all.js (line 7)


    Now functionally everything basically works... you can simply close the window manually and all is as normal, however this creates a big usability issue. When some one is using the component, they have no clue whether what they did actually worked or not.

    Anyhow, I've looked at MODx.Window and MODx.FormPanel for any clues on things I can override, but didn't find anything that made sense to me.

    Below is the success response I receive from the processor:
    {"success":true,"message":"","total":0,"data":[],"object":{"id":17,"custId":37,"email":"[email protected]","products":"[{\"id\":\"sku-1:119317930\",\"title\":\"CE5+ Kits\",\"colors\":\"blue\",\"sizes\":\"small\",\"styles\":\"leopard-print\",\"quantity\":1,\"price\":68,\"options\":\"{\\\"colors\\\":{\\\"id\\\":\\\"1\\\",\\\"name\\\":\\\"colors\\\",\\\"value\\\":\\\"blue\\\"},\\\"sizes\\\":{\\\"id\\\":\\\"3\\\",\\\"name\\\":\\\"sizes\\\",\\\"value\\\":\\\"small\\\"},\\\"styles\\\":{\\\"id\\\":\\\"11\\\",\\\"name\\\":\\\"styles\\\",\\\"value\\\":\\\"leopard-print\\\"}}\",\"limit\":0,\"weight\":0,\"stock\":0,\"taxable\":true},{\"id\":\"sku-2:-599076262\",\"title\":\"Carto Kit I\",\"color\":\"blue\",\"quantity\":1,\"price\":65,\"options\":\"{\\\"color\\\":{\\\"id\\\":\\\"21\\\",\\\"name\\\":\\\"color\\\",\\\"value\\\":\\\"blue\\\"}}\",\"limit\":0,\"weight\":0,\"stock\":0,\"taxable\":true}]","name":"Jared","address":"P.O. Box 555","city":"Olympia","state":"WA","zip":"98502","phone":"5555555555","deliveryMethod":"USPS Flate Rate","paymentMethod":"","comments":"","subtotal":"133","shipping":"0.01","tax":"11.17","total":"144","status":"2","trackingno":null,"createdon":"2013-05-18 20:23:22","createdby":37,"editedon":null,"editedby":0,"action":"mgr\/orders\/update","HTTP_MODAUTH":"REMOVED-Incase-this-is-a-security-issue"}}


    and lastly, my grid and windows..
    jShop.grid.Orders = function(config) {
        config = config || {};
        Ext.applyIf(config,{
            id: 'jshop-grid-orders'
            ,url: jShop.config.connectorUrl
            ,baseParams: { action: 'mgr/orders/getList' }
            ,fields: ['id','custId','email','products','name','oname','address','addr','city','state','zip','phone','deliveryMethod','paymentMethod','comments','subtotal','shipping','tax','total','status','trackingno','createdon','editedon']
            ,paging: true
    		,pageSize: 10
    		,save_action: 'mgr/orders/updateFromGrid'
    		,autosave: true
            ,remoteSort: true
            ,anchor: '97%'
            ,autoExpandColumn: 'name'
            ,columns: [{
                header: _('js.order_id')
                ,dataIndex: 'id'
                ,sortable: true
                ,width: 60
            },{
                header: _('js.order_name')
                ,dataIndex: 'name'
                ,sortable: true
                ,width: 125
                //,editor: { xtype: 'textfield' }
            },{
                header: _('js.order_address')
                ,dataIndex: 'address'
                ,sortable: false
                ,width: 125
    			,renderer: {fn:this._renderAddress,scope:this}
                //,editor: { xtype: 'textfield' }
            },{
                header: _('js.order_trackingno')
                ,dataIndex: 'trackingno'
                ,sortable: false
                ,width: 125
                ,editor: { xtype: 'textfield' }
            },{
               header: _('js.order_total')
               ,dataIndex: 'total'
               ,sortable: true
               ,width: 60
    		,renderer: {fn:this._renderTotal,scope:this}
               //,editor: { xtype: 'textfield' }
            },{
               header: _('js.order_status')
               ,dataIndex: 'status'
               ,sortable: true
               ,width: 100
               ,editor: {
    		    xtype: 'modx-combo'
    		    ,renderer: true
    		    ,url: jShop.config.connectorUrl    
    		    ,baseParams: {
    		         action: 'mgr/status/getList'
    		    	}
    			}
            },{
    			header: _('js.order_createdon')
    			,dataIndex: 'createdon'
    			,sortable: true
    			,width: 100
    		}]
    		,tbar:[{
    		   text: _('js.order_create')
    		   ,handler: function() { 
    				window.location.href = '?a='+MODx.action['jshop:index']+'&action=item';
    			}
    		},'->',{
    		    xtype: 'textfield'
    		    ,id: 'jshop-search-filter'
    		    ,emptyText: _('js.search...')
    		    ,listeners: {
    		        'change': {fn:this.search,scope:this}
    		        ,'render': {fn: function(cmp) {
    		            new Ext.KeyMap(cmp.getEl(), {
    		                key: Ext.EventObject.ENTER
    		                ,fn: function() {
    		                    this.fireEvent('change',this);
    		                    this.blur();
    		                    return true;
    		                }
    		                ,scope: cmp
    		            });
    		        },scope:this}
    		    }
    		},'-',{
    			xtype: 'datefield'
    			,emptyText: _('js.filterOrderStart')
    			,id: 'jshop-orderstart-filter'
    			,listeners: {
    				select: {fn:this.filterOrderStart, scope: this}
    				,scope: this
    			}
    			,width: 200
    		},'-',{
    			xtype: 'datefield'
    			,emptyText: _('js.filterOrderEnd')
    			,id: 'jshop-orderend-filter'
    			,listeners: {
    				select: {fn:this.filterOrderEnd, scope: this}
    				,scope: this
    			}
    			,width: 200
    		},'-',{
    			xtype: 'modx-combo'
    			,renderer: true
    			,url: jShop.config.connectorUrl    
    			,baseParams: {
    				action: 'mgr/status/getList'
    			}
    			,emptyText: _('js.order_status_select')
    			,id: 'jshop-status-filter'
    			,width: 200
    			,listeners: {
    				'select': {fn: this.filterByStatus, scope: this}
    			}
            },'-',{
    		   xtype: 'button',
    		   text: 'Clear Filter',
    		   listeners: {
    		   	'click': {fn: this.clearFilter, scope: this}
    		   }
    		}]
    		
        });
        jShop.grid.Orders.superclass.constructor.call(this,config);
    	this._makeTemplates();
    };
    Ext.extend(jShop.grid.Orders,MODx.grid.Grid,{
        search: function(tf,nv,ov) {
            var s = this.getStore();
            s.baseParams.query = tf.getValue();
            this.getBottomToolbar().changePage(1);
            this.refresh();
        },filterOrderStart: function(tf) {
            var s = this.getStore();
            s.baseParams.ostart = tf.getValue();
            this.getBottomToolbar().changePage(1);
            this.refresh();
        },filterOrderEnd: function(tf) {
            var s = this.getStore();
            s.baseParams.oend = tf.getValue();
            this.getBottomToolbar().changePage(1);
            this.refresh();
        },filterByStatus: function (cb, rec, ri) {
            this.getStore().baseParams['status'] = rec.data['id'];
            this.getBottomToolbar().changePage(1);
            this.refresh();
        },clearFilter: function() {
            this.getStore().baseParams['query'] = '';
            this.getStore().baseParams['status'] = '';
    		this.getStore().baseParams['ostart'] = '';
    		this.getStore().baseParams['oend'] = '';
            Ext.getCmp('jshop-search-filter').reset();
            Ext.getCmp('jshop-status-filter').reset();
    		Ext.getCmp('jshop-orderstart-filter').reset();
    		Ext.getCmp('jshop-orderend-filter').reset();
            this.getBottomToolbar().changePage(1);
            this.refresh();
        },getMenu: function() {
    		var m = [];
    	    m.push({
    	        text: _('js.order_update')
    	        ,handler: this.updateOrder
    			,scope: this
    	    }/*,'-',{
            text: _('js.order_remove')
            ,handler: this.removeOrder
    	    }*/);
    		if (this.menu.record.custId >= 1) {
    			m.push('-',{
    		        text: _('js.user_update')
    		        ,handler: this.updateUser
    		    });
    		}
    		return m;
    	},updateOrder: function(btn,e) {
    		if (!this.updateOrderWindow) {
                this.updateOrderWindow = MODx.load({
                    xtype: 'jshop-window-order-update'
                    ,record: this.menu.record
    				,oid: this.menu.record.id
                    ,listeners: {
                        'success': {fn:this.refresh,scope:this}
                    }
                });
            }
    		this.updateOrderWindow.record = this.menu.record;
            this.updateOrderWindow.setValues(this.menu.record);
            this.updateOrderWindow.show(e.target);
            var itemsgrid = Ext.getCmp('jshop-grid-items');
            itemsgrid.store.baseParams = {action: 'mgr/orders/getitemlist',id: this.menu.record.id || 0 ,start: 0 ,limit: itemsgrid.config.pageSize};
    		itemsgrid.store.load();
    	},updateUser: function(btn,e) {
    		window.location.href = '?a='+MODx.request['a']+'&action=user&id='+this.menu.record.custId;
    	},removeOrder: function() {
    	    MODx.msg.confirm({
    	        title: _('js.order_remove')
    	        ,text: _('js.order_remove_confirm')
    	        ,url: this.config.url
    	        ,params: {
    	            action: 'mgr/orders/remove'
    	            ,id: this.menu.record.id
    	        }
    	        ,listeners: {
    	            'success': {fn:this.refresh,scope:this}
    	        }
    	    });
    	},_makeTemplates: function() {
    		this.tplTotal = new Ext.XTemplate('<tpl for=".">'
                +'<div class="order-total-column"><span class="currency">$</span><span class="order-total">{total}</span></div>'
            +'</tpl>',{
    			compiled: true
    		});
            this.tplAddress = new Ext.XTemplate('<tpl for="."><div class="order-address-column">'
    										    +'<p class="main-column"><span class="order-address">{address}, </span><span class="order-city">{city}, </span><span class="order-state">{state} </span><span class="order-zip">{zip}</span></p>'
    											+'</tpl>',{
    			compiled: true
    		});
        }
    	,_renderAddress:function(v,md,rec) {
    		return this.tplAddress.apply(rec.data);
    	}
    	,_renderTotal:function(v,md,rec) {
    		return this.tplTotal.apply(rec.data);
    	}
    });
    Ext.reg('jshop-grid-orders',jShop.grid.Orders);
    
    jShop.window.UpdateOrder = function(config) {
    	config = config || {};
    	Ext.applyIf(config,{
    		title: _('js.order_update')
    		,url: jShop.config.connectorUrl
    		,baseParams: {
    			action: 'mgr/orders/update'
    		}
    		,width: '800'
    		,fields: [{
    			xtype: 'hidden'
    			,name: 'id'
    			,id: 'js-oid'
    		},{
    			xtype: 'modx-tabs'
    			,autoHeight: true
    			,deferredRender: false
    			,forceLayout: true
    			,border: true
    			,defaults: {
    				border: false
    				,autoHeight: true
    				,layout: 'form'
    				,deferredRender: false
    				,forceLayout: false
    				,cls: 'main-wrapper'
    			}
    			,items: [{
    				title: _('js.order_info')
    				,items: [{
    					layout: 'column'
    					,items: [{
    						columnWidth: .6
    						,border:true
    						,layout: 'form'
    						,items: [{
    							xtype: 'fieldset'
    							,title: _('js.order_shippinginfo')
    							,items: [{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_name')
    								,name: 'oname'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_address')
    								,name: 'addr'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_phone')
    								,name: 'phone'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_deliveryMethod')
    								,name: 'deliveryMethod'
    								,anchor: '100%'
    							}]
    						}]
    					},{
    						columnWidth: .4
    						,border: true
    						,layout: 'form'
    						,items: [{
    							xtype: 'fieldset'
    							,title: _('js.order_totals')
    							,items: [{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_subtotal')
    								,name: 'subtotal'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_shipping')
    								,name: 'shipping'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_tax')
    								,name: 'tax'
    								,anchor: '100%'
    							},{
    								xtype: 'statictextfield'
    								,fieldLabel: _('js.order_total')
    								,name: 'total'
    								,anchor: '100%'
    							}]
    						}]
    					}]
    				},{
    					xtype: 'fieldset'
    					,title: _('js.order_items')
    					,items: [{
    						xtype: 'jshop-grid-items'
    					}]
    				}]
    			},{
    				title: _('js.order_edit')
    				,items: [{
    					layout: 'column'
    					,items: [{
    						columnWidth: .6
    						,border: true
    						,layout: 'form'
    						,items: [{
    							xtype: 'fieldset'
    							,title: _('js.order_shippinginfo')
    							,items: [{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_name')
    								,name: 'name'
    								,anchor: '100%'
    							},{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_address')
    								,name: 'address'
    								,anchor: '100%'
    							},{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_city')
    								,name: 'city'
    								,anchor: '100%'
    							},{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_state')
    								,name: 'state'
    								,anchor: '100%'
    							},{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_zip')
    								,name: 'zip'
    								,anchor: '100%'
    							}]
    						}]
    					},{
    						columnWidth: .4
    						,border: true
    						,layout: 'form'
    						,items: [{
    							xtype: 'fieldset'
    							,title: _('js.order_stattrack')
    							,items: [{
    								xtype: 'combo'
    								,displayField: 'name'
    								,valueField: 'id'
    								,forceSelection: true
    								,store: new Ext.data.JsonStore({
    									root: 'results'
    									,idProperty: 'id'
    									,url: jShop.config.connectorUrl
    									,baseParams: {
    										action: 'mgr/status/getlist'
    									}
    									,fields: [ 'id','name' ]
    								})
    								,mode: 'remote'
    								,triggerAction: 'all'
    								,fieldLabel: _('js.status')
    								,name: 'status'
    								,hiddenName: 'status'
    								,allowBlank: false
    								,typeAhead: false
    								,minChars: 1
    								,emptyText: _('js.status_select')
    								,valueNotFoundText: _('js.status_notfound')
    								,anchor: '100%'
    							},{
    								xtype: 'textfield'
    								,fieldLabel: _('js.order_trackingno')
    								,name: 'trackingno'
    								,anchor: '100%'
    							}]
    						},{
    							xtype: 'fieldset'
    							,title: _('js.order_totals')
    							,items: [{
    								xtype: 'button'
    								,text: _('js.order_override_totals')
    								,handler: this.overrideTotals
    								,scope: this
    							}]
    						}]
    					}]
    				},{
    					layout: 'column'
    					,items: [{
    						columnWidth: 1
    						,border: true
    						,layout: 'form'
    						,items: [{
    							xtype: 'fieldset'
    							,title: _('js.order_comments')
    							,items: [{
    								xtype: 'textarea'
    								,name: 'comments'
    								,anchor: '100%'
    							}]
    						}]
    					}]
    				}]
    				
    			}]
    		}]
    	});
    	jShop.window.UpdateOrder.superclass.constructor.call(this,config);
    };
    Ext.extend(jShop.window.UpdateOrder,MODx.Window,{
    	overrideTotals: function(btn,e) {
    		//console.log(this.record);
    		if (this.overrideTotalsWindow) {
    			this.overrideTotalsWindow.reset();
    		}
    		this.overrideTotalsWindow = MODx.load({
    			xtype: 'jshop-window-override-totals'
    			,record: this.record
    			,listeners: {
    				'success': {fn:this.refresh,scope:this}
    			}
    		});
    		this.overrideTotalsWindow.setValues(this.record);
            this.overrideTotalsWindow.show(e.target);
        }
    });
    Ext.reg('jshop-window-order-update',jShop.window.UpdateOrder);
    
    jShop.window.OverrideTotals = function(config) {
    	config = config || {};
    	Ext.applyIf(config,{
    		title: _('js.order_override_totals')
    		,url: jShop.config.connectorUrl
    		,baseParams: {
    			action: 'mgr/orders/update'
    		}
    		,fields: [{
    			xtype: 'hidden'
    			,name: 'id'
    		},{
    			xtype: 'textfield'
    			,fieldLabel: _('js.order_subtotal')
    			,name: 'subtotal'
    			,anchor: '100%'
    		},{
    			xtype: 'textfield'
    			,fieldLabel: _('js.order_tax')
    			,name: 'tax'
    			,anchor: '100%'
    		},{
    			xtype: 'textfield'
    			,fieldLabel: _('js.order_shipping')
    			,name: 'shipping'
    			,anchor: '100%'
    		},{
    			xtype: 'textfield'
    			,fieldLabel: _('js.order_total')
    			,name: 'total'
    			,anchor: '100%'
    		}]
    	});
    	jShop.window.OverrideTotals.superclass.constructor.call(this,config);
    };
    Ext.extend(jShop.window.OverrideTotals,MODx.Window);
    Ext.reg('jshop-window-override-totals',jShop.window.OverrideTotals);


    I'd greatly appreciate any tips or advice...

    Thanks in advance!
    -Jared