Success! Looks like we've fixed this one. According to our records the fix was applied for EXTJS-5935 in a recent build.
  1. #1
    Ext JS Premium Member
    Join Date
    Nov 2011
    Posts
    35
    Vote Rating
    0
    JamaSoftware-Sencha is on a distinguished road

      0  

    Default 4.1.RC3: Error removing item afterRender: ownerContext.target.ownerLayout not defined

    4.1.RC3: Error removing item afterRender: ownerContext.target.ownerLayout not defined


    Example page:

    HTML Code:
    <html>
    <head>
        <script type="text/javascript" src="/resources/extjs-4.1.0-rc3/ext-all-debug.js"></script>
    
    </head>
    
    <body>
    
    
        <script type="text/javascript">
    
            Ext.onReady(function() {
                
                Ext.create('Ext.container.Container', {
                    renderTo: Ext.getBody(),
                    layout: 'auto',
                    style: 'background-color: #eeeeee',
                    items: [{
                            xtype: 'component',
                            html: '<a href="javascript: addItem();">Add Item #1</a> &nbsp; &nbsp; &nbsp;' +
                                '<a href="javascript: addOtherItem();">Add Item #2</a>'
                        },
                            
                            window.myct1 = Ext.create('Ext.container.Container', {
                                //width: 400,
                                //height: 200,
                                style: 'background-color: blue'
                            }),
                            window.myct2 = Ext.create('Ext.container.Container', {
                                //width: 400,
                                //height: 200,
                                style: 'background-color: green'
                            })
                        ]
                });
                
                Ext.define('jx.MyComponent', {
                    extend: 'Ext.Component',
                    width: 400,
                    height: 100,
                    style: 'background-color: yellow',
                    html: 'View error in console<br/>Note that specifying width/height on the blue and green containers fixes the issue',
                    afterRender: function() {
                        this.callParent(arguments);
                        window.myct1.remove(window.mychild, true);
                    }
                });
                
            });
            
            function addItem() {
                window.mychild = Ext.create('Ext.Component', {
                    html: 'Child component #1 (will be removed on #2 afterrender)',
                    width: 400,
                    height: 50,
                    style: 'background-color: red'
                });
                
                window.myct1.add(window.mychild);
            }
            
            function addOtherItem() {
                window.myct2.add(Ext.create('jx.MyComponent'));
            }
        
        </script>
        
    </body>
    </html>
    To reproduce:
    • Open example page
    • Click "Add Item #1"
    • Click "Add Item #2"
    • Error shows in console, and first item doesn't get removed
    One strange workaround is to uncomment the width/height I've commented out for the two containers. Thus it would seem this issue has something to do with Ext not managing the size of the children or something.

  2. #2
    Ext JS Premium Member
    Join Date
    Nov 2011
    Posts
    35
    Vote Rating
    0
    JamaSoftware-Sencha is on a distinguished road

      0  

    Default


    The workaround we have implemented for now is to remove the item from the container after deferring 1ms.

    In the above code, this would be:

    Code:
    Ext.defer(window.myct1.remove, 1, window.myct1, [window.mychild, true]);

  3. #3
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,496
    Vote Rating
    44
    Animal has a spectacular aura about Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Yes, that will work.

    The problem is that in the afterRender function, you are inside a layout run.

    And that component which you then remove has an entry in the layout Context which is scheduled to perform some layout stuff.

    So a remove must cancel the layout. And a destroy must remove the component's corresponding LayoutContext from its parent LayoutContext.

    Otherwise as the Context continues processing its queue, it hits the removed Component which has no ownerLayout and no ownerCt and no el any more.

  4. #4
    Sencha User
    Join Date
    Mar 2012
    Posts
    35
    Vote Rating
    0
    Patlatus is on a distinguished road

      0  

    Default


    I have the same error in other places


    'Ext.layout.Context',

    Code:
     layoutDone: function (layout) {
          var ownerContext = layout.ownerContext,
              ownerCtContext;
    
    
          layout.running = false;
    
    
          
          
          
          if (layout.isComponentLayout) {
              if (ownerContext.measuresBox) {
                  ownerContext.onBoxMeasured(); 
              }
    
    
              ownerContext.setProp('done', true);
    
    
              ownerCtContext = ownerContext.ownerCtContext;
              //the following line is the only changed line in this function
              if (ownerCtContext && !Ext.isEmpty(ownerContext.target.ownerLayout)) {
                  if (ownerContext.target.ownerLayout.isComponentLayout) {
                      if (! --ownerCtContext.remainingComponentChildLayouts) {
                          ownerCtContext.setProp('componentChildrenDone', true);
                      }
                  } else {
                      if (! --ownerCtContext.remainingContainerChildLayouts) {
                          ownerCtContext.setProp('containerChildrenDone', true);
                      }
                  }
                  if (! --ownerCtContext.remainingChildLayouts) {
                      ownerCtContext.setProp('childrenDone', true);
                  }
              }
          } else {
              ownerContext.setProp('containerLayoutDone', true);
          }
    
    
          --this.remainingLayouts;
          ++this.progressCount; 
      },
    
    
    
    
    
    
    
    
      resetLayout: function (layout, ownerContext, firstTime) {
          var me = this,
              ownerCtContext;
    
    
          me.currentLayout = layout;
    
    
          layout.done = false;
          layout.pending = true;
          layout.firedTriggers = 0;
    
    
          me.layoutQueue.add(layout);
    
    
          if (firstTime) {
              me.layouts[layout.id] = layout; 
              layout.running = true;
    
    
              if (layout.finishedLayout) {
                  me.finishQueue.add(layout);
              }
    
    
              
    
    
              ++me.remainingLayouts;
              ++layout.layoutCount; 
    
    
              layout.beginCount = 0; 
              layout.blockCount = 0; 
              layout.calcCount = 0; 
              layout.triggerCount = 0; 
    
    
              
              if (layout.isComponentLayout && (ownerCtContext = ownerContext.ownerCtContext)) {
                  
                  
                 // the following "if" condition is the only change in this function
                 if (!Ext.isEmpty(ownerContext.target.ownerLayout)) {
                     
                     if (ownerContext.target.ownerLayout.isComponentLayout) {
                         ++ownerCtContext.remainingComponentChildLayouts;
                     } else {
                         ++ownerCtContext.remainingContainerChildLayouts;
                     }
                     ++ownerCtContext.remainingChildLayouts;
                 }
              }
    
    
              if (!layout.initialized) {
                  layout.initLayout();
              }
    
    
              layout.beginLayout(ownerContext);
          } else {
              ++layout.beginCount;
    
    
              if (!layout.running) {
                  
                  ++me.remainingLayouts;
                  layout.running = true;
    
    
                  if (layout.isComponentLayout) {
                      
                      
                      
                      ownerContext.unsetProp('done');
    
    
                      
                      
                      
                      ownerCtContext = ownerContext.ownerCtContext;
                      if (ownerCtContext) {
                          if (ownerContext.target.ownerLayout.isComponentLayout) {
                              if (++ownerCtContext.remainingComponentChildLayouts == 1) {
                                  ownerCtContext.unsetProp('componentChildrenDone');
                              }
                          } else {
                              if (++ownerCtContext.remainingContainerChildLayouts == 1) {
                                  ownerCtContext.unsetProp('containerChildrenDone');
                              }
                          }
                          if (++ownerCtContext.remainingChildLayouts == 1) {
                              ownerCtContext.unsetProp('childrenDone');
                          }
                      }
                  }
    
    
                  
                  me.completionQueue.remove(layout);
                  me.finalizeQueue.remove(layout);
              }
          }
    
    
          layout.beginLayoutCycle(ownerContext, firstTime);
      }


    class

    'Ext.layout.component.Component',


    Code:
    beginLayoutCycle: function (ownerContext, firstCycle) {
          var me = this,
              owner = me.owner,
              ownerCtContext = ownerContext.ownerCtContext,
              heightModel = ownerContext.heightModel,
              widthModel = ownerContext.widthModel,
              body = owner.el.dom === document.body,
              lastBox = owner.lastBox || me.nullBox,
              lastSize = owner.el.lastBox || me.nullBox,
              dirty = !body,
              ownerLayout, v, widthName, heightName;
    
    
          me.callParent(arguments);
    
    
          if (firstCycle) {
              if (me.usesContentWidth) {
                  ++ownerContext.consumersContentWidth;
              }
              if (me.usesContentHeight) {
                  ++ownerContext.consumersContentHeight;
              }
              if (me.usesWidth) {
                  ++ownerContext.consumersWidth;
              }
              if (me.usesHeight) {
                  ++ownerContext.consumersHeight;
              }
    
    
              if (ownerCtContext && !ownerCtContext.hasRawContent) {
                  ownerLayout = owner.ownerLayout;
    
    
                  // the following "if" condition is the only change in this function
                  if (!Ext.isEmpty(ownerLayout)) {
                     if (ownerLayout.usesWidth) {
                         ++ownerContext.consumersWidth;
                     }
                     if (ownerLayout.usesHeight) {
                         ++ownerContext.consumersHeight;
                     }
                  }
              }
          }
          
          if (widthModel.configured) {
              
              
              
              
              widthName = widthModel.names.width;
    
    
              if (!body) {
                  dirty = firstCycle ? owner[widthName] !== lastSize.width
                                     : widthModel.constrained;
              }
              
              ownerContext.setWidth(owner[widthName], dirty);
          } else if (ownerContext.isTopLevel) {
              if (widthModel.calculated) {
                  v = lastBox.width;
                  ownerContext.setWidth(v, v != lastSize.width);
              }
    
    
              v = lastBox.x;
              ownerContext.setProp('x', v, v != lastSize.x);
          }
    
    
          if (heightModel.configured) {
              heightName = heightModel.names.height;
    
    
              if (!body) {
                  dirty = firstCycle ? owner[heightName] !== lastSize.height
                                     : heightModel.constrained;
              }
    
    
              ownerContext.setHeight(owner[heightName], dirty);
          } else if (ownerContext.isTopLevel) {
              if (heightModel.calculated) {
                  v = lastBox.height;
                  ownerContext.setHeight(v, v != lastSize.height);
              }
    
    
              v = lastBox.y;
              ownerContext.setProp('y', v, v != lastSize.y);
          }
      }
    
    
    });





    one more error here
    class
    'Ext.view.Table',

    Code:
    onUpdate : function(store, record, operation, changedFieldNames) {
          var me = this,
              index,
              newRow, oldRow,
              oldCells, newCells, len, i,
              columns, overItemCls,
              isHovered, row;
              
          if (me.rendered) {
              
              index = me.store.indexOf(record);
              columns = me.headerCt.getGridColumns();
              overItemCls = me.overItemCls;
    
    
              
              
              if (columns.length && index > -1) {
                  newRow = me.bufferRender([record], index)[0];
                  oldRow = me.all.item(index);
                  // the following "if" condition is the only change in this function
                  if (!Ext.isEmpty(oldRow)){
                     isHovered = oldRow.hasCls(overItemCls);
                     oldRow.dom.className = newRow.className;
                     if(isHovered) {
                         oldRow.addCls(overItemCls);
                     }
    
    
                     
                     oldCells = oldRow.query(this.cellSelector);
                     newCells = Ext.fly(newRow).query(this.cellSelector);
                     len = newCells.length;
                     
                     row = oldCells[0].parentNode;
                     for (i = 0; i < len; i++) {
                         
                         if (me.shouldUpdateCell(columns[i], changedFieldNames)) {
                             row.insertBefore(newCells[i], oldCells[i]);
                             row.removeChild(oldCells[i]);
                         }
                     }
                  }
    
    
    
    
                  
                  
                  me.selModel.refresh();
                  me.doStripeRows(index, index);
                  me.fireEvent('itemupdate', record, index, newRow);
              }
          }
    
    
      }

Thread Participants: 2

Tags for this Thread