PDA

View Full Version : [solved]Ext.Direct load data in extended Form fails (scope issue)



Wolfgang
1 Apr 2010, 9:11 AM
Hello,

when loading data into an extend form, i always get


this.form is undefined
[Break on this error] this.form.afterAction(this, false);
ext-all-debug.js (Zeile 65958)

(Note: this linenumber refers to ext 3.2.0 that has been released today - thank you :-))
Submit works just fine.

At that line, it seems that "this" point to the global window object instead to the form.

Before that happens - arround line 63138-63141 it looks good.


load : function(options){
var loadAction = String.format('{0}load', this.api ? 'direct' : '');
this.doAction(loadAction, options);
return this;
},

loadAction == "directload" and this == the form.

Maybe this thread is related: http://www.extjs.com/forum/showthread.php?t=86826

Here the code - am i doing something wrong - is this an ext scope issue?



Ext.ns('Ext.app');
Ext.app.AddHostForm = Ext.extend(Ext.form.FormPanel, {
bodyStyle: 'padding:10px;'
,autoScroll:true

,initComponent: function(){
var config = {
api: {
load: rpc.Hosts.get
,submit: rpc.Hosts.addHost
}
,defaultType: 'textfield'
,items: [{
fieldLabel: 'Hostname'
,name: 'hostname'
,allowBlank:false
}
,{
fieldLabel: 'User Name'
,name: 'username'
,allowBlank:false
}
,{
fieldLabel: 'Password'
,inputType: 'password'
,name: 'password'
,allowBlank:false
}] // oe items

,buttons:[{
text:'Load'
,scope:this
,handler:this.onLoad
}
,{
text:'Submit'
,scope:this
,handler:this.onSubmit
}] // oe buttons

};

Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.app.AddHostForm.superclass.initComponent.apply(this, arguments);
} // oe initComponent


// direct load handler
,onLoad: function() {
this.getForm().load({
params: {
id: 1
}
,success: function() {
console.log('load success');
}
,failure: function() {
console.log('load failure');
}
});
} // eo onLoad

// direct submit handler
,onSubmit: function() {
this.getForm().submit({
params: {id: 2}
,success: function() {
console.log('submit success');
}
,failure: function() {
console.log('submit failure');
}
});
} //eo onSubmit

});
Ext.reg('appaddhostform', Ext.app.AddHostForm);


Any help / hint is very much appreciated - Thank you

steffenk
1 Apr 2010, 1:29 PM
I had same problems and got enlightenment here:
http://www.extjs.com/forum/showthread.php?t=95267

Wolfgang
1 Apr 2010, 1:59 PM
Steffen thank you - but i still need a bit more enlightment, even after reading your thread.
From Ext Form.js:


// private
createForm : function(){
var config = Ext.applyIf({listeners: {}}, this.initialConfig);
return new Ext.form.BasicForm(null, config);
},

i see i need to have set initialConfig. But this is what i have done in my code :-?


Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.app.AddHostForm.superclass.initComponent.apply(this, arguments);


also - removing the api definition from initComponent and adding an onRender method does not help:


// does not work neither - independent wether to call superclass before or after Ext.apply
,onRender: function() {

//Ext.app.AddHostForm.superclass.onRender.apply(this, arguments);
Ext.apply(this.getForm(),{
api: {
load: rpc.Hosts.get
,submit: rpc.Hosts.addHost
}
,paramsAsHash: false
});
Ext.app.AddHostForm.superclass.onRender.apply(this, arguments);
}

steffenk
2 Apr 2010, 7:02 AM
the latest is the one i use in my forms. Are you sure you have proper formHandler set? Is there a request?

here is a working formPanel i use:

Ext.ns('TYPO3.EM');

TYPO3.EM.TerUpload = Ext.extend(Ext.form.FormPanel, {
border:false,
recordData: null,

initComponent:function() {



Ext.apply(this, {
itemId: 'extUploadForm',
height: 340,
defaultType: 'textfield',

defaults: {width: 350},
items: [{
fieldLabel: 'Repository Username',
name: 'fe_u'
}, {
fieldLabel: 'Repository Username',
inputType: 'password',
name: 'fe_p'
}, {
fieldLabel: 'Changelog for upload',
xtype: 'textarea',
height: 150,
name: 'uploadcomment'
}, {
xtype: 'radiogroup',
fieldLabel: 'New Version',
itemCls: 'x-check-group-alt',
columns: 1,
items: [
{boxLabel: 'New bugfix version (latest x.x.<strong><span class="typo3-red">x+1</span></strong>)', name: 'newversion', inputValue: 'new_dev',checked: true},
{boxLabel: 'New sub version (latest x.<strong><span class="typo3-red">x+1</span></strong>.0)', name: 'newversion', inputValue: 'new_sub'},
{boxLabel: 'New main version (latest <strong><span class="typo3-red">x+1</span></strong>.0.0)', name: 'newversion', inputValue: 'new_main'}
]
}, {
xtype: 'button',
text: 'Upload extension',
scope: this,
handler: function() {
this.form.submit({
waitMsg : 'Sending data...',
success: function(form, action) {
TYPO3.Flashmessage.display(1,'TER Upload', 'Extension was uploaded to TER', 5);
form.reset();
},
failure: function(form, action) {
if (action.failureType === Ext.form.Action.CONNECT_FAILURE) {
TYPO3.Flashmessage.display(3, 'Error',
'Status:'+action.response.status+': '+
action.response.statusText, 5);
}
if (action.failureType === Ext.form.Action.SERVER_INVALID){
// server responded with success = false
TYPO3.Flashmessage.display(3, 'Invalid', action.result.errormsg, 5);
}
}
});
}
}],
listeners: {

activate: function(panel) {


}
},
scope: this
});

TYPO3.EM.TerUpload.superclass.initComponent.apply(this, arguments);
},

onRender: function() {


TYPO3.EM.TerUpload.superclass.onRender.apply(this, arguments);

Ext.apply(this.getForm(),{
api: {
load: TYPO3.EM.ExtDirect.loadUploadExtToTer,
submit: TYPO3.EM.ExtDirect.uploadExtToTer
},
paramsAsHash: false

});
this.form.load();
}


});

Ext.reg('terupload', TYPO3.EM.TerUpload);

Wolfgang
2 Apr 2010, 2:24 PM
Thank you very much steffen.

Well after some hours of debugging i finally got it running.
Ok first the fix - it looks pretty easy (set either paramsAsHash:true or paramOrder: ['id'])


,initComponent: function(){
var config = {
api: {
load: rpc.Hosts.get
,submit: rpc.Hosts.addHost
}
//,paramOrder: ['id'] // really important! either this
,paramsAsHash: true // or this - otherwise error! this.form. ist not an object...


Really simple once you know this.
But why does it lead to such an error?
All we do is to define how params are sent during a load event using Ext.direct / "directload"?

We have some issues to think about:
a.) Where to put the api:{} and paramOrder/paramsAsHash properties?
b.) How to use paramOrder/paramsAsHash?
c.) Is there anything else important?

About a.)
This was the issue that steffen found/solved (But this was not the issue i faced)
"api" and "paramOrder/paramsAsHash" must be set in initComponent or in onRender/afterRender.
The reason for this is in Ext.FormPanel:


createForm : function(){
var config = Ext.applyIf({listeners: {}}, this.initialConfig);
return new Ext.form.BasicForm(null, config);
},


About b.)
"paramOrder" or set "paramsAsHash:true" must be set. This is important!
The reason for this is that Ext.form.Action.DirectLoad.getParam() would return an empty array.
If both properties are set, "paramOrder" takes preference.
Have a look here:


getParams : function() {
var buf = [], o = {};
var bp = this.form.baseParams;
var p = this.options.params;
Ext.apply(o, p, bp);
var paramOrder = this.form.paramOrder;
if(paramOrder){
for(var i = 0, len = paramOrder.length; i < len; i++){
buf.push(o[paramOrder[i]]);
}
}else if(this.form.paramsAsHash){
buf.push(o);
}
return buf;
},

getParams() also revels the "secret" of paramsAsHash. Basically (as the name implies) it defines how the called loadhandler in the backend gets the params: Either all params in one hash or as seperate params.

About c.)
Well, what happens if no param is specified or if both paramsAsHash/paramOrder is not set?
In this case one get the error i ran into.
But why?
The first step to the answer is again in Ext.form.Action.DirectLoad:


run : function(){
var args = this.getParams();
args.push(this.success, this);
this.form.api.load.apply(window, args);
},

The first push would be the result of getParams().
But bc i had not set paramsAsHash/paramOrder, this was an empty array.

This leads to trouble in Ext.direct.RemotingProvider:


doCall : function(c, m, args){
var data = null, hs = args[m.len], scope = args[m.len+1];

args should be


args[param, function, form]

but was


args[function, form]

However with m.len == 1


hs = args[m.len], scope = args[m.len+1];

became a mess.

Summary:
- When using Ext.direct with a form - you must use either "paramsAsHash:true" or "paramOrder:['myparam']".
- When extending such a form, you must set those properties, along with "api" either in initComponent or on/afterRender.

Thanks for reading - I know this is quite a long post but i hope it helps others to get a better understanding.

Wolfgang

sjerry
2 May 2010, 1:30 AM
run : function(){
var args = this.getParams();
args.push(this.success, this);
this.form.api.load.apply(window, args);
},

I still get the "this.processResponse is not a function" error, even though everything looks fine. I hope you can clarify the flow of the scope.

Is "this" in args.push(this.success, this); the scope for "this.success" callback?

Do ExtDirect functions take a third param for the scope of the callback? For example: Products.getAll('ASC', callback, this)? :-/

When i do: args.push(this.success.createDelegate(this), this); everything works the way it should be...

In the code above, the scope (in my case) is "Ext.form.Action.DirectLoad". After the server response is received and the success callback is invoked, the scope in the callback is "window". I think it should be the action scope

Wolfgang
6 May 2010, 12:36 AM
After the server response is received and the success callback is invoked, the scope in the callback is "window". I think it should be the action scope
This is correct.

Can you show more code, especially the form?

perler
18 Aug 2010, 7:55 AM
run : function(){
var args = this.getParams();
args.push(this.success, this);
this.form.api.load.apply(window, args);
},

I still get the "this.processResponse is not a function" error, even though everything looks fine. I hope you can clarify the flow of the scope.

Is "this" in args.push(this.success, this); the scope for "this.success" callback?

Do ExtDirect functions take a third param for the scope of the callback? For example: Products.getAll('ASC', callback, this)? :-/

When i do: args.push(this.success.createDelegate(this), this); everything works the way it should be...

In the code above, the scope (in my case) is "Ext.form.Action.DirectLoad". After the server response is received and the success callback is invoked, the scope in the callback is "window". I think it should be the action scope

I'm having the same problem with the same error message. The scope is set to window and thus the method cannot be called. Did someone solve this?

zwlee
22 Mar 2011, 1:40 AM
This is correct.

Can you show more code, especially the form?

hello!
when i used directload method,
I have encountered another problem, when the connect is failured, like 404 error,
the ext-all.js will run into an error: a is undefined!!

did you ever encountered this situation too??