PDA

View Full Version : [OPEN-989] alignToXY error when dynamically adding/removing Numberfield from Panel



brownphillipa
19 May 2010, 5:19 PM
Hi all,

I have an Ext window which consists of a couple of forms. The first form has a dropdown combo, and depending on which value the user selects, the second form gets populated/repopulated.

The layout is as follows



Window
|
|--FormPanel1 --[Combobox1]
|
|--FormPanel2
|
|---Panel(ColumnLayout1)
|
|---FormPanel3--[ ]
|
|---FormPanel4--[ ]



Based on what the users selects in Combobox1, form items are dynamically removed and added into ColumnLayout1 and 2.

I am populating ColumnLayout1 with a numberfield that has allowBlank: false so if the field is blank, it gets underlined in red and i have the Quicktip exclamation mark on the side. If this textfield has a valid number in it, and i choose a different option in combobox1, all my textfields get destroyed and re-rendered with new data as defined in my Combobox listener.


However if the numberfield in FormPanel3 or 4 is blank, and i try to select a new option in Combobox1, the items are destroyed but not recreated because the Quicktip/red underline still exists (i think) and is trying to align itself to an item that no longer exists. I get an 'Uncaught Element.alignToXY with an element that doesn't exist' error. I thought it might be quicktips causing the issue, so i tried disabling quicktips but i still get this error if the field is blank.

I've tried setting allowBlank to true and calling clearInvalid() just before removing the numberfield but i still get the error.

Code is as follows: (I have a few columnlayouts nested in there in order to get side by side fields)




this.mainForm.getPorts.getForm().submit({
var this = parent;
success: function(form, action) {

parent.mainForm.sapPanel.columnContainerTop.left.removeAll(true);
parent.mainForm.sapPanel.columnContainerTop.right.removeAll(true);
.
.
.
}



I also tried changing the value to something valid on blur in order to get rid of the quicktip/error, but still no luck.



scope: this,
listeners:{
blur: {
fn: function() {
if (this.getValue() == "")
{
this.setValue(0);
this.clearInvalid();
Ext.QuickTips.unregister(this.getEl());
}
else
{
//Do nothing
}


I would think that when i call removeAll() on the parent formpanel, the validation/quicktips would be destroyed as well? I haven't added any custom listeners. Any ideas?

jsakalos
20 May 2010, 12:32 PM
Do you call doLayout() after you add items?

Note: Is it really necessary to destroy/re-create items? Wouldn't show/hide or a card layout do better?

brownphillipa
20 May 2010, 4:41 PM
I realized i was probably calling doLayout() a bit too early in the dynamic adding/removing process so i removed that. I've also redesigned the layout a little bit so that theres only one or two numberfields that are being dynamically added/removed.

I could probably find a workaround rather than destroying and recreating, but it would still be nice to know how to dynamically remove numberfields from a form.

I've found if i disable quicktips and add a blur handler that changes the value of the numberfield to a non blank value then i have no issues, but if i enable quicktips, i get an error. If i don't have the blur handler, i get the error.

Would an Ext.Quicktips.unregister() for the numberfield work? Or does unregister only work for quicktips that have been manually added to an element?

jsakalos
21 May 2010, 1:40 AM
I have no real idea what's going on here. Normally, you can call form.add() and form.remove() and it should be w/o any consequences if done properly and form.doLayout() is called afterwards. Can you post a complete but simplest possible showcase so that we call look into it? You may have discovered a bug.

brownphillipa
22 May 2010, 5:31 PM
Hi Saki,

Here is some complete code that displays the behaviour:



Ext.onReady(function () {
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = "side";

var mainPanel = new Ext.form.FormPanel({
title: 'test form',
layout: 'form',
id: 'parentForm',
frame: true,
items: [
{
xtype: 'combo',
fieldLabel:'Mode',
ref: 'combo',
name:'combotest',
forceSelection:true,
store: new Ext.data.ArrayStore({
fields: [
{
name:'mode',
type: 'string'
}
],
data: [['Beginner'], ['Advanced']]
}),
mode: 'local',
triggerAction: 'all',
allowBlank: false,
editable:false,
selectOnFocus: true,
displayField: 'mode',
listeners:{
select:{
fn: function() {
this.ownerCt.columnContainerBottom.left.removeAll();
var value = this.getValue();
switch (value) {
case 'Beginner':
this.ownerCt.columnContainerBottom.left.add(
new Ext.form.NumberField({
fieldLabel: 'Beginner field',
ref: 'beginner',
name: 'beginner',
allowBlank: false,
allowDecimals: false,
allowNegative: false,
maxValue: 4095,
width: 50
}) );
break;

case 'Advanced':
this.ownerCt.columnContainerBottom.left.add(
new Ext.form.NumberField({
fieldLabel: 'Advanced field',
ref: 'advanced',
name: 'advanced',
allowBlank: false,
allowDecimals: false,
allowNegative: false,
maxValue: 4095,
width: 50
}) );
break;
}
this.ownerCt.columnContainerBottom.left.doLayout();
}
}
}
},
{
layout: 'column',
ref: 'columnContainerBottom',
height: 100,
items: [
{
columnwidth: .5,
layout: 'form',
ref: 'left',
width: 200
},{
columnwidth: .5,
layout: 'form',
ref: 'right',
width: 200
}
]
}
]
});

new Ext.Viewport({
layout: 'fit',
items: [
mainPanel
]
});
});


If you select Beginner from the dropdown, and type a backspace in the numberfield displayed so that a quicktip is shown (alternatively type in a value greater than 4095 since that will also cause a quicktip to be shown), then choose Advanced from the numberfield, you'll get an error in firebug/chrome inspector saying 'Uncaught Element.alignToXY with an element that doesn't exist'. As soon as quicktips is disabled, this error is no longer encountered. I have used removeAll() and doLayout() in the example.


edit: I guess this is being caused by Ext.form.Field.prototype.msgTarget = "side"; ? Does that mean it's not possible to have quicktips displayed on the side for form items that are to be dynamically added and removed?

jsakalos
23 May 2010, 1:20 AM
It looks like a bug. Field::el still exists but its dom is already destroyed. This is the quick fix:


Ext.override(Ext.form.Field, {
alignErrorIcon : function(){
if(this.el.dom) {
this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
}
}
});


Moving this thread to bugs.

bariand
28 Sep 2010, 2:06 AM
Any news about this issue?
In my code remove all field from a fieldset but when inserting them again I get the error about an uncaught exception.
The workaround you provided doesn't seem to work...

bariand
4 Nov 2010, 2:31 AM
Hi,
I tried with ExtJS 3.3.0 but this issue is still there.
Any news or suggestion?

Thanks

masood
21 May 2012, 2:57 PM
Thanks for the fix. Works great!