PDA

View Full Version : Can't have two treepanels extended from the same class at the same time



dirtdevil
30 Jul 2012, 3:21 PM
I get this error when I have 2 tree panels extended from a common tree panel.
Uncaught TypeError: Cannot read property 'isComponent' of undefined

Since my code is split out in multiple files, I stripped it down to just the bug and zipped it up. It's only a few files and it's very very small. I tried using xtypes. I read the learning docs on the main tutorial page. I'm going nuts with this issue because I know it's something in the CoreTree class. I can have one tree work fine or the other tree but not both. To make my code work, I have to comment out one of the trees from loading to make it work.

evant
30 Jul 2012, 3:31 PM
If you want help with Ext, please post in the Ext specific forum. Moving.

vietits
30 Jul 2012, 5:52 PM
I have run your example code with Ext 4.1.1 and I saw both trees displayed at the same time, one in "Tree1" tab and one in "categories" tab.

dirtdevil
30 Jul 2012, 6:15 PM
The copy of Ext I got is only a week old. That can't be right. I just ran that same code and it still broke. I'm using is v4.1.1 I tried it in chrome and firefox.

dirtdevil
30 Jul 2012, 7:11 PM
nevermind. I figured it out. Turns out you can't use the plugins config option on a tree panel you have other classes extending from. I put the plugins option on the two tree directly and took it off of the core tree and it worked fine. But why? Why wouldn't I be able to add plugins to a class I'm extending other classes from?

vietits
30 Jul 2012, 7:27 PM
That's because you create and share objects at prototype. Try to fix that by initializing objects in initComponent(). For example:



Ext.define('Test.view.tree.CoreTree', {
extend: 'Ext.tree.Panel',
requires: [
'Ext.grid.plugin.CellEditing',
'Ext.tree.plugin.TreeViewDragDrop',
'Ext.grid.column.Action'
],
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
dragText: 'Drag to reorder',
ddGroup: 'task'
}
},
initComponent: function(){
var me = this;

Ext.applyIf(me, {
plugins: [
Ext.create('Ext.grid.plugin.CellEditing')
]
});
me.callParent(arguments);
},
listeners: {
itemclick: function( v, m, node, num ){
}
}
});

dirtdevil
30 Jul 2012, 7:40 PM
Thanks for the help. I was wondering, when working with custom extended classes, is it better to just stuff everything in initComponent to make sure everything gets loaded properly?

skirtle
30 Jul 2012, 8:09 PM
Shoving everything in initComponent will avoid shared reference problems but it's considerably less elegant and it introduces flexibility problems if you try to subclass further.

You may find this helpful:

http://skirtlesden.com/articles/config-objects-on-the-prototype

For plugins you can use ptypes to avoid shared references:


plugins: [{
ptype: 'cellediting'
}]

dirtdevil
31 Jul 2012, 8:41 AM
Great article, that cleared up a lot of things for me. A question...

You mentioned in your article that it's not a good idea to init objects on the prototype due to causing problems. You gave an example about multiple grids using the same store. But there have been times where I have had multiple grids that I want to use the same store because both grids show the same data in different ways and when the data changes, I want a way to refresh both grids at the same time. They can still sort and filter on there own but if there is a change in the store, I want anything that uses that store to refresh it's self. How would I go about doing that without causing problems in the class?

skirtle
31 Jul 2012, 10:33 PM
Sharing stores is difficult. It's important to understand that the sorting and filtering are as much a part of the store as the data itself. If you need different sorting and filtering then you need two stores. Records can be shared between stores as of 4.1.0 but if you're performing adds/removes then you'll just have to listen to suitable events and propagate the changes yourself.

dirtdevil
1 Aug 2012, 9:02 AM
Thats what I figured. As a work around, I've just used separate stores with the same fetch urls and when I do change on one store, I add an event to reload the other stores, which is just another fetch url request. While I have your attention, I have a question that's off topic...

As far as the new widget/alias system, I understand it's used by xtypes but what else could it be used for? The only time I use the alias config is when I'm going to load that class as an xtype. I've never really had another reason for an alias: 'something' entry in a class.

skirtle
1 Aug 2012, 9:38 PM
Aliases can be used for all sorts of things.

If you refer back to my earlier answer you'll see I suggested configuring a plugin using:


plugins: [{
ptype: 'cellediting'
}]

If you dig into the source for CellEditing you'll find this:


alias: 'plugin.cellediting',

The alias gives the plugin its ptype.

Another common example is stores. If you want to create several identical stores you can do it by subclassing store:


Ext.define('MyStore', {
alias: 'store.mystore',
extend: 'Ext.data.Store',
...
});

Then when you need a store for a component you can use:


store: {type: 'mystore'}

The same principle applies to many other types of class. You've probably created proxies and readers via their aliases without even realising it. You can see numerous examples in the article I posted previously: wherever you see a class specified via a type (or xtype, ptype, ftype, ...) it's being resolved via an alias behind the scenes. Take a browse of the ExtJS source code to see what types of alias exist.

skirtle
6 Aug 2012, 3:26 PM
Please post these questions as separate threads. The idea behind the Q&A forum is that you ask a single question (plus related follow-up questions) and then mark the best answer, a bit like Stack Overflow.

dirtdevil
6 Aug 2012, 3:41 PM
done. Thanks for the heads up.