PDA

View Full Version : [Solved] deep inheritence SimpleForm->Form->BasicForm [now with extra scope issue]



TheNakedPirate
21 Aug 2007, 10:36 PM
I have hit a bit of a wall over this and a complete answer to this problem might be a a real penny-dropper for me, elevating my understanding of object oriented javascript from noob to padawan.

Anyhow the problem goes like this.

I have written a "simple" class. It inherits from Ext.form.Form which in turn inherits from Ext.form.BasicForm. The idea of the class being that everyform I write will have a submit button with a success and failure method that has the same method.



SimpleForm = function(config) {
// call the superclass
SimpleForm.superclass.constructor.call(this, config);

this.successUrl = config.successUrl;

this.addButton(
{
text: 'Save', cls: 'x-btn-text-icon save', handler: this.onSubmit
});

};

Ext.extend(SimpleForm, Ext.form.Form,
{
successUrl: null,

onSubmit: function(o, e)
{
if (this.isValid())
{
this.submit({params:{action:'submit'},
success: function(action, form)
{
if(this.successUrl)
{
self.location = this.successUrl;
}
},
failure: function(){Ext.MessageBox.alert("Failure", "There was a problem submitting this item.");},
waitMsg:'Saving...'});
}
else
{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
}
});

groovy

so I call it



/*
* ================ form =======================
*/
var pageForm = new Dfat.page.SimpleForm({
labelWidth: 200, // label settings here cascade unless overridden
successUrl: 'view.rails?id=2',
url:'update.rails'
});

pageForm.add(
new Ext.form.TextField({fieldLabel: 'Iso Name' ,readOnly: false ,name: 'Country.Name' ,width: 260 ,value: "Bolivia" ,allowBlank: false})
, new Ext.form.HiddenField({ name: 'Country.Id' ,value: '2'})
);

pageForm.render('form-ct');It renders just fine and look great "thanks Ext".

but when I press the submit button I get a message in Firebug saying this.isValid() is not a function.

But it is I tell you...it's two levels up in BasicForm.

I tried doing this SimpleForm.superclass.isValid.call(this)
and that tells me that this.items is no good.

So what am I doing wrong? how do i correct it?

Animal
21 Aug 2007, 11:05 PM
this.addButton(
{
text: 'Save', cls: 'x-btn-text-icon save', handler: this.onSubmit
});


The handler will execute in the scope of the window. The "this" object when that executes will be the window.

http://extjs.com/learn/Manual:Utilities:Function

See last parameter:

http://extjs.com/deploy/ext/docs/output/Ext.form.Form.html#addButton

TheNakedPirate
22 Aug 2007, 4:48 PM
Thank you thank you thank you thank you thank you.

I was reading about scope in one of the stickies but didn't really get how it applied to my problem

So the solution ended up with me adding a 'scope: this' at the end of the button config.



this.addButton(
{
text: 'Save', cls: 'x-btn-text-icon save', handler: this.onSubmit, scope: this
});
I can start having a family life again.

Thank you thank you thank you thank you thank you.

=D>

TheNakedPirate
23 Aug 2007, 8:10 PM
Close one door open another.

I am having trouble with scope again.

The submit success method needs to refer to a property in my class. I'm guessing that because the success function runs somewhere up in the BasicForm scope the this bit is pointing some where else. How do I break the scope out of inline functions that run in different scope space?

this.successUrl = undefined
this.cancelUrl = http://a-url-of-usefulness/default.rails



Dfat.page.SimpleForm = function(config) {

Dfat.page.SimpleForm.superclass.constructor.call(this, config);

this.successUrl = config.successUrl;
this.cancelUrl = config.cancelUrl;

this.addButton(
{
text: 'Save', cls: 'x-btn-text-icon save', handler: this.onSubmit, scope: this
});

this.addButton(
{
text: 'Cancel', cls: 'x-btn-text-icon cross', handler: this.onCancel, scope: this
});

};

Ext.extend(Dfat.page.SimpleForm, Ext.form.Form,
{
successUrl: null,

onSubmit: function(o, e)
{
if (this.isValid())
{
this.submit({params:{action:'submit'},
success: function(action, form)
{
alert(this.successUrl);
if(this.successUrl)
{
self.location = this.successUrl;
}
},
failure: function()
{
Ext.MessageBox.alert("Failure", "There was a problem submitting this item.");
},
waitMsg:'Saving...'});
}
else
{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
},

onCancel: function(o, e)
{
if(this.cancelUrl)
{
self.location = this.cancelUrl;
}
}
});

TheNakedPirate
23 Aug 2007, 8:40 PM
Just so you know, I am getting around it this way but it all kinda sucks a bit




onSubmit: function(o, e)
{
var hostClass = this;
if (this.isValid())
{
this.submit({params:{action:'submit'},
success: function(action, form)
{
if(hostClass.successUrl)
{
self.location = hostClass.successUrl;
}
},
failure: function()
{
Ext.MessageBox.alert("Failure", "There was a problem submitting this item.");
},
waitMsg:'Saving...'});
}
else
{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
},

evant
23 Aug 2007, 9:46 PM
This is exactly the same problem. You aren't giving the callback a scope to execute in, so it will default to window.

TheNakedPirate
23 Aug 2007, 10:10 PM
This is exactly the same problem. You aren't giving the callback a scope to execute in, so it will default to window.

Yeah I get that, but and when animal suggested applying the scope option it was pretty clear in the addButton method how to do that.



this.addButton(
{
text: 'Save', cls: 'x-btn-text-icon save', handler: this.onSubmit, scope: this
});


but the onsuccess event delegate needs a function and, noob that I am, I can't see how to add scope to that particular call other than by holding a reference to the current class in a local variable.

So is my
var hostClass = this; solution the right way, that is, a best practice, or is it a kludge?

I have tried a few things and I am pretty certain I understand the 'what' part of the problem but syntactically the 'how' eludes me. :-?

evant
23 Aug 2007, 10:12 PM
This should do it:


onSubmit: function(o, e)
{
var hostClass = this;
if (this.isValid())
{
this.submit({params:{action:'submit'},
scope: this,
success: function(action, form)
{
if(hostClass.successUrl)
{
self.location = hostClass.successUrl;
}
},
failure: function()
{
Ext.MessageBox.alert("Failure", "There was a problem submitting this item.");
},
waitMsg:'Saving...'});
}
else
{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
},

TheNakedPirate
24 Aug 2007, 1:25 AM
thanks its good to know im on the right track

organic
26 Sep 2007, 8:51 PM
I have problem to call superclass functions

superclass:

Tcp.Bubble =function(config){

return{
size: function(w, h) {
this.w = parseFloat(w);
this.h = parseFloat(h);
return this;
}
};


}();

subclass:

Tcp.MapBubble = function(config) {
Tcp.MapBubble.superclass.constructor.call(this, config);
this.sz = this.size(WIDTH, HEIGHT);
return this;
}
Ext.extend(Tcp.MapBubble,Tcp.Bubble,{
var WIDTH = 353;
var HEIGHT = 225;
});

i am getting the error " this.size is not a function

anyone help me to find the solution
Thanks
organic

evant
26 Sep 2007, 9:22 PM
Because Tcp.Bubble is a singleton class.