PDA

View Full Version : [SOLVED] Multiple Instances of Component - form render problems - scope issue?



Nigel
1 Aug 2011, 3:33 AM
Hi

I used Animal's excellent tutorial article (Tutorial:Creating_new_UI_controls (http://bugtracker.extjs.com/learn/Tutorial:Creating_new_UI_controls)) to create a new component, my first serious attempt at a brand new component rather than enhancement and extension of existing components.

The component is pretty simple - it displays an image, and on right-clicking the image, presents a form which allows for upload of a replacement image.
Everything works beautifully until I have more than one instance of the component at once - then the form panel on both instances created gets messed up on render of the second panel - attached image 1 shows the correct first display, image 2 shows what happens when there is another one displayed at the same time.

I thought I'd made a serious error with the scope of the formPanel or formWindow variables, or that it is something to do with these being set on the prototype rather than in each 'instance' of the component - but I've been testing variables and components in FireBug and Illuminations and digging deeper into the source code, but still can't find the problem. I'm worried that it's a really basic javascript misunderstanding on my part about the scope of variables within a component object or prototype - and I'd really like to plug that knowledge gap so I can sleep better :)

I know that ultimately I should sort this out so I only have one instance of the form panel, and hide/show it for each image, updating its config on the fly so the communication with the back-end works for the correct image. I will do this anyway, but my bigger concern right now is that I don't truly understand WHY this is happening, despite plenty of digging and thinking.

Component code below (running in Ext3.3.1)

xampe.UI.Image = Ext.extend(Ext.Component, {
formWindow: null,
formPanel: null,

// http://bugtracker.extjs.com/learn/Tutorial:Creating_new_UI_controls
autoEl: {
tag: 'img',
src: Ext.BLANK_IMAGE_URL,
border: 1
},

onRender: function () {
this.autoEl = Ext.apply({}, this.initialConfig, this.autoEl);

xampe.UI.Image.superclass.onRender.apply(this, arguments);

this.el.on('contextmenu', this.onContextMenu, this);
},

onContextMenu: function () {
if (this.formWindow === null) {
this.formPanel = new Ext.FormPanel({
fileUpload: true,
width: 300,
autoHeight: true,
monitorValid: true,
baseParams: {
item_id: this.item_id
},
bodyStyle: 'padding: 10px 10px 0 10px;',
labelWidth: 50,
defaults: {
anchor: '90%',
allowBlank: false,
msgTarget: 'side'
},
items: [{
xtype: 'xfileuploadfield',
id: 'form-file',
emptyText: xampe.Lang.SelectImage,
vtype: 'imageFile',
fieldLabel: xampe.Lang.Image,
name: 'image-path',
buttonText: '',
buttonCfg: {
iconCls: 'icon-image'
}
}],
buttonAlign: 'center',
buttons: [{
text: xampe.Lang.Upload,
formBind: true,
handler: function () {
var form;

form = this.formPanel.getForm();

if (form.isValid()) {
form.submit({
url: 'xampe/app/xampe.image.php',
waitMsg: xampe.Lang.UploadingImage,
success: function (fp, o) {
if (o.result.success) {
MyApp.setStatusMessage(xampe.Lang.ImageUploadSuccess);
this.hideForm();
this.refreshSrc();
} else {
MyApp.setStatusError(String.format('{0}: {1}', xampe.Lang.ImageUploadFailure,
o.result.error));
}
},
scope: this
});
}
},
scope: this
}, {
text: xampe.Lang.Cancel,
handler: function () {
this.hideForm();
},
scope: this
}]
});

this.formWindow = new Ext.Window({
width: 300,
layout: 'fit',
header: false,
resizable: false,
closable: false,
border: false,
baseClass: 'x-panel',
cls: 'x-window',
autoHeight: true,
items: [this.formPanel]
});
}

var pos = this.el.getAlignToXY(this.el, 'tl-b?');
this.formWindow.setPagePosition(pos[0], pos[1]);
this.formWindow.show();
},

hideForm: function () {
this.formWindow.items[0].getForm().reset();
this.formWindow.hide();
},

onDestroy: function () {
Ext.destroy(this.formWindow);
xampe.UI.Image.superclass.onDestroy.apply(this, arguments);
},

setSrc: function (src) {
if (this.rendered) {
this.el.dom.src = src;
} else {
this.src = src;
}
},

refreshSrc: function () {
this.setSrc(this.src + '?rand=' + Math.random());
}
});
Ext.reg('ximage', xampe.UI.Image);Thanks in advance for any help
Nigel

Nigel
24 Aug 2011, 2:31 AM
How embarassing - I've fixed this - the problem was really straight-forward. I'd hard-coded an id on the form item, which resulted in the DOM messing up big-time when trying to build the second form with an element of the same id. The really stupid bit was that I wasn't even subsequently referring to the element by id!


id: 'form-file',



I think that's known in the trade as a 'schoolboy-error'! :">

Nigel