2

I've created a fiddle just to simulate my problem with class property not being reset on window destroy.
How to test: Open fiddle, press OPEN button, ADD 3 panels, close ext window, press OPEN button again, and add a some more panels.
Panel numbers represent the length of the _panels array property in window.
Now to the problem.
As you can see panel NUMBER when adding new panels is not reset. So if you add 3 panels and close the window, reopen the window panels count shows 3 and then 4 and then 5 instead of 0 1 2 ...
My question is, why?

Fiddle example

Kind regards

Armando

EDIT : so one can see the solution
I ended fixing my application to work like this fiddle. I moved properties to constructor.

constructor: function() {
    Ext.apply(this, {     
        width: 800,      
        height: 600, 
        layout: 'vbox', 
        _panels : []
    }); 
    this.callParent(arguments); 
},
Armando
  • 137
  • 10

3 Answers3

1

The simple answer for this is prototypal inheritance (see this MDN article). Basically your non-primitives will carry over to new instances because they exist on your prototype class, and because they're non-primitives, it's the same exact reference that's used. To fix this, I would recommend wrapping your _panels variable in the config block, like below, and encourage you to use the appropriate set/get methods, instead of accessing it directly:

config: {
    _panels : []
}
incutonez
  • 3,241
  • 9
  • 43
  • 92
  • I moved them to constructor as I want to have these properties "private" – Armando Sep 15 '20 at 18:55
  • 1
    You could still use the config approach but mark it as `private` with a comment if it's a concern, but what you did is another totally acceptable approach to this. – incutonez Sep 15 '20 at 19:28
  • 1
    you can use onDestroy: function() { this._panels.length = 0 },. It will empty the array. – Ovais Sep 15 '20 at 19:50
  • 1
    @Ovais - you don't want to do that, because the `_panels` reference is being shared with other instances of the class (because, as incutonez said, it's coming from the prototype). The right solution is to make it _not_ be shared. – Robert Watkins Sep 15 '20 at 22:01
  • I ended fixing my application to work like this [fiddle](https://fiddle.sencha.com/#view/editor&fiddle/38s9). I moved properties to constructor. ` constructor: function() { Ext.apply(this, { width: 800, height: 600, layout: 'vbox', _panels : [], }); this.callParent(arguments); },` – Armando Sep 16 '20 at 17:15
1

When you define

Ext.define('TestWindow', {
    extend: 'Ext.window.Window',
    _panel: []
});

The TestWindow definition class gets empty array property (no-primitive datatype). When you create an instance by var win = Ext.create('TestWindow'), the instance gets that property. However, when you set:

   onDestroy: function() {
      this._panels = [];
    },

it sets empty array to property _panels of the instance win, not on the definition class TestWindow; TestWindow keeps the existing mutated _panel. And when next time you create new instance, it gets same _panel from class definition.

I understand you did it for demo purpose to show the problem. However, I prefer to let framework do all heavy-lifting (create and destroy etc):

Ext.define('TestWindow', {
    extend: 'Ext.window.Window',

    width: 800,
    height: 600,

    defaultListenerScope: true,
    layout: 'vbox',

    initComponent: function() {
        this._panels = [];
        this.callParent(arguments);
    },

    addPanel: function() {
        console.log(this._panels.length);
        
        var panels = this._panels;
        panels.push(this.add({
            xtype: 'panel',
            title: 'Panel ' + panels.length,
            height: 50,
            width: '100%'
        }));
    },
    
    tbar: [{
        xtype : 'button',
        text: 'add',
        handler: 'addPanel'
    }]

});
Ovais
  • 374
  • 2
  • 7
  • Forgot to mention that move `this._panels = [];` inside `initComponent` to make it instance specific. – Ovais Sep 16 '20 at 19:05
  • yeah I agree with your answer I just did the same in constructor ... cause I'm used to initilize classes in contructors :D – Armando Sep 16 '20 at 19:17
0

A less than correct answer if the prototype behavior in the previous answer is "A feature/intentional bad code/ legacy code with unintended consequences"

Manually overwrite the prototype Value, following instantiation of the panel

manually overwrite _.panels

Akin Okegbile
  • 1,108
  • 19
  • 36
  • Note, the "Less than correct answer" that references points made in previous answer. If you are in a legacy system, where the bad behavior was there before, it can be problematic to correct. Also accept the previous answer, as it answers the question. – Akin Okegbile Sep 16 '20 at 17:52