PDA

View Full Version : An inheritance problem



lisper
22 Aug 2011, 8:50 AM
I'm running the demo code found here:

http://docs.sencha.com/ext-js/4-0/#/guide/application_architecture

I'm trying to extend this code to add and delete users. To do this, I added a "delete" button to the Edit view. This works.

To add a new user I need a window that looks exactly like the old Edit view (without the delete button). So I added this. That works too. But now I have duplicated code in the Add and Edit views which I want to refactor. I want Edit to inherit from Add with the addition of a delete button. So I tried this:



Ext.define('MyApp.view.user.Edit', { extend: 'MyApp.view.user.Add',
alias : 'widget.useredit',


title : 'Edit User',


initComponent: function() {
this.callParent(arguments);
this.buttons.push({ text: 'Delete', action: 'delete' })
}
});


This fails with the following error:

TypeError: Result of expression 'me.buttons' [null] is not an object.

The reason this happens is that the call to this.callParent(arguments) in MyApp.view.user.Add sets the buttons property to null, i.e. if I put this at the end of MyApp.view.user.Add.initComponent:



console.log(this.buttons);
this.callParent(arguments);
console.log(this.buttons);

The output is:

[Object, Object]
null

So... what is the right way to do this?

lisper
22 Aug 2011, 2:05 PM
I think this might actually be related to this bug:

http://www.sencha.com/forum/showthread.php?128740-FIXED-EXTJSIV-586-FormPanel-button-formBind-true-dont-work-on-form-reset

The bug in question is about formBind not working, but the underlying cause could be the same, namely, the initComponent method nuking the list of buttons when it shouldn't be.

Just sayin'

:-?

skirtle
23 Aug 2011, 12:20 AM
I think your diagnosis is slightly off. I believe the this.buttons array is processed during initComponent(), so pushing an extra config on the end of the array after you call initComponent() won't have any effect anyway. Setting it to null is just housekeeping.

You have a number of options to get this working. You could do some painful stuff involving retrieving the toolbar and inserting an extra item. If you don't have access to the code for the superclass then this might be your only option. However, it sounds like you do have access to the code for both classes so there's a much more elegant way to do it using a template method to create the config.

I've simplified the code a little but the principle is hopefully clear.


Ext.define('MyApp.view.user.Add', {
extend: 'Ext.window.Window',

initComponent: function() {
this.buttons = this.createButtonsConfig();
this.callParent();
},

createButtonsConfig: function() {
return [
{text: 'Add'},
{text: 'Edit'}
];
}
});

Ext.define('MyApp.view.user.Edit', {
extend: 'MyApp.view.user.Add',

createButtonsConfig: function() {
var buttons = this.callParent();
buttons.push({text: 'Delete'});

return buttons;
}
});

lisper
23 Aug 2011, 8:49 AM
Thanks!

One more followup question: I want to bind my submit button to the form so that it is inactive when the form fields are invalid. It's easy to do this with an Ext.form.Panel (just specify "formBind: true" in the submit button*) but is there an easy way to do the same thing when your form and buttons are inside an Ext.window.Window?

I tried the obvious thing of extending Ext.form.Panel instead of Ext.window.Window to make my edit view, but that didn't work. I also tried the less obvious thing of manually sticking my button in the form's _boundItems property. That didn't work either.

---

*There is a known bug that prevents this from working, but there's also a workaround (http://www.sencha.com/forum/showthread.php?128740-FIXED-EXTJSIV-586-FormPanel-button-formBind-true-dont-work-on-form-reset).

skirtle
23 Aug 2011, 8:10 PM
Implementing an imitation of formBind should be easy enough:


Ext.define('MyApp.view.user.Add', {
extend: 'Ext.window.Window',

layout: 'fit',

initComponent: function() {
this.buttons = this.createButtonsConfig();

this.items = [{
border: false,
xtype: 'form',

items: [
... // your fields go here
],

listeners: {
scope: this,
validitychange: function(form, valid) {
Ext.each(this.query('[formBind]'), function(button) {
button.setDisabled(!valid);
});
}
}
}];

this.callParent();
},

createButtonsConfig: function() {
return [
{text: 'Add', formBind: true},
{text: 'Edit', formBind: true}
];
}
});

lisper
23 Aug 2011, 9:38 PM
That worked. That "listeneres" incantation is apparently what I needed. Thanks!
:)