PDA

View Full Version : [4.0.0] MVC data.TreeStore and controller: this.store is undefined



medusadelft
30 Apr 2011, 2:35 AM
Hi,

Despite the efforts of unit testing, it seems like MVC is not completely finished/tested yet in the final 4.0 code.
I run into several problems (groupField on grid, see help-forum, searchfield store problem, root-property needs to be defined in the controller instead of store for a TreePanel (see help-forum), referencing to a component from a controller needs the use of prototype eg: Ex.view.tree.Tree.prototype.expandAll) and now again I get this message (again, store related):


this.store is undefined
http://localhost/ext-4.0.0/ext-all-debug.js
Line 87251

return this.store.getRootNode()


I just have a toolbar in a TreePanel with a button. From the controller I want to call the expandAll function...


If someone of the Dev-team needs an example, I'm happy give my code.


I'm really excited about the new stuff and developing apps using MVC seems easier (my first attempt to MVC, when it is working), but I agree with some people that this version (4.0.0) should be a Beta4. It is just not stable enough and lacks good documentation (I might have overlooked it, but I can't find the properties for trees like 'leaf', 'iconCls' etc, the search bar on top is not clickable. Slow loading, host not reachable sometimes).
At least I'm glad I haven't bought a license yet and that I have not committed myself for any clients to use ExtJs-4.
The framework is very promissing, but a lot of bugs should be fixed really quick before people running away and use something else less buggy. I also bought ExtDesigner some time ago, but no support for 4.0 when ExtJS 4 is released also makes me sad (I know it's coming, but when? and probably with a lot of errors again and likely no MVC structure possibility)

I still like the effort the Dev team puts in and ExtJs in general. It's visually the best javascript framework and I am a fan from the beginning. So keep up the good work and I'm sure a lot of bugs will be fixed in the forthcoming 4.0.1. I just can't wait till it's released!

Maurice.

Nickname
30 Apr 2011, 11:15 AM
Had the same problem with releases before beta3. At this time regStore was not deprecated, but the problem is the same.
No one from Sencha gave a hint or marked this as a bug and I'm tired to push the thread (http://www.sencha.com/forum/showthread.php?129982-RegStore-and-Treepanel-TreeStore-define-store-as-string-in-treepanel).
Perhaps you have more luck than I have ;)

wcravens
1 May 2011, 9:30 AM
The following demonstrates the getRootNode failure using the examples/app/simple application:



diff --git a/app/store/Users.js b/app/store/Users.js
index fbf8f55..c4de03d 100644
--- a/app/store/Users.js
+++ b/app/store/Users.js
@@ -1,5 +1,5 @@
Ext.define('AM.store.Users', {
- extend: 'Ext.data.Store',
+ extend: 'Ext.data.TreeStore',
model: 'AM.model.User',
autoLoad: true,

@@ -15,4 +15,4 @@ Ext.define('AM.store.Users', {
successProperty: 'success'
}
}
-});
\ No newline at end of file
+});
diff --git a/app/view/user/List.js b/app/view/user/List.js
index 731a1d9..7c684fc 100644
--- a/app/view/user/List.js
+++ b/app/view/user/List.js
@@ -1,5 +1,5 @@
Ext.define('AM.view.user.List' ,{
- extend: 'Ext.grid.Panel',
+ extend: 'Ext.tree.Panel',
alias : 'widget.userlist',

title : 'All Users',


The workaround for this (for me) was to create the TreeStore inline with the TreePanel. However even then it doesn't seem to firing loads for 'ajax'/'rest' proxies.

mxracer
1 May 2011, 10:07 AM
I have been creating an app while looking to the MVC guide for instruction and I ran into this issue as well. My solution for now (not sure if its correct for long term) is in code below.

Define my store in app/store/Folders.js


Ext.define('MY.store.Folders', {
extend: 'Ext.data.TreeStore',
folderSort: true,
proxy: {
extraParams: {
c: 'folders_controller',
m: 'get'
},
type: 'ajax',
url: 'server/index.php'
},
sorters: [
{
property: 'sort_order',
direction: 'ASC'
}
]
});


Now define my tree in app/view/folder/Tree.js



Ext.define('MY.view.folder.Tree', {
extend: 'Ext.tree.Panel',
...
initComponent: function () {
this.store = Ext.create('MY.store.Folders', {
listeners: {
load: {
fn: this.onFoldersLoad,
scope: this
}
},
root: {
text: 'My Root',
expanded: true
}
});

this.callParent(arguments);
},
...
});

wcravens
2 May 2011, 4:11 AM
The trick is to have some root configuration in the TreePanel (even if blank).

See: http://www.sencha.com/forum/showthread.php?130680-TreeStore-supported-in-MVC



Ext.define('MyTree', {
extend: 'Ext.tree.Panel',
store: 'MyTreeStore'
...
//KLUDGE : Workaround for this thread
root: { }
});

mohanimus
2 May 2011, 8:19 PM
From the API Docs:



root : Boolean

Allows you to not specify a store on this TreePanel. This is useful for creating a simple tree with preloaded data without having to specify a TreeStore and Model. A store and model will be created and root will be passed to that store.


The above approaches (specifying a root config or instantiating the store in the view) seem to violate the intent of the MVC approach where stores are created in the controller.

It makes sense to me to have some partial definition of the root node that is used for the initial request from the store. However when I try this approach (letting the controller instantiate the store) it appears to be creating a store without a getRootNode method.

mohanimus
2 May 2011, 10:54 PM
For even more giggles...

I have defined a store that extends TreeStore, a panel that extends TreePanel and have wired it all up according to the MVC intro docs. This produces the error "me.store.getRootNode is not a function" as described above.

However, in the firebug console "Ext.StoreManager.lookup('MyStore').getRootNode()" returns a well formatted node object.

mohanimus
3 May 2011, 12:07 AM
Finally got it working almost to my satisfaction.

Note for reference I am working with an inline store (specifying it's data with a root config) as opposed to a remoting store for which the empty root in the panel config may be more elegant.

My fix is a simple modification of the initComponent creation version above.



Ext.define('MY.view.MyTree', {
extend: 'Ext.tree.Panel',
store: 'MyStore',
initComponent: function () {
this.store = Ext.StoreManager.lookup(this.store);
this.callParent(arguments);
}
});


This does however allow you to use the store created in the controller :)

Now on to working out how to fix the width of this panel when you put it in an Accordion >.<

bas_tzx
3 May 2011, 2:33 AM
I also struggled with the TreePanel, MVC and Stores in the beginning. The solution is to include a reference to your store in the Controller and have a rootNode defined in the View (treePanel). Just follow the latest MVC guide which you can find in the API docs.



// Define the Store
Ext.define('My.store.Folders', {
extend: 'Ext.data.TreeStore',

proxy: {
type: 'ajax',
url: 'folders/tree.php'
}
});

// Define the View
Ext.define('My.view.folders.Tree', {
extend: 'Ext.tree.Panel',
alias: 'widget.foldertree',

// Define root here as a workaround
root: {
text: 'root node'
},
rootVisible: false,

store: 'Folders', // The store loaded by the Controller

initComponent: function () {
// Do something here

this.callParent(arguments);
}
});

// Define the controller
Ext.define('My.controller.Folders', {
extend: 'Ext.app.Controller',

// Stores to load
stores: ['Folders'],

// Views to load
views: [
'folders.Tree'
],

init: function () {
// Control
this.control({
'foldertree': {
'itemclick': this.openItem
}
});
},

openItem: function() {}
});

wcravens
3 May 2011, 3:13 AM
bas_tzx: Would you mind referencing the 'MVC Guide' more specifically? I couldn't/can't find a MVC TreePanel/TreeStore example in the guide/s anywhere.

Typically I reference local documentation and expect the online docs to also remain in static until a new release is available for download (but I can understand why this may not be the Sencha strategy). So I double checked the current online docs and I still can't seem to find a MVC example of a TreePanel/TreeStore.

Thanks.

bas_tzx
3 May 2011, 4:20 AM
You are right about the the absence of a specific Tree/MVC example, but because of the way ExtJS is setup, it's very easy to replace one panel/component with another. In the MVC example you can just replace the grid panel (view) with a tree panel (and you can also leave out the model, because it's not required for the tree).

And the online docs seem do get updated regularly. Recently Sencha added a guide about the Tree: http://dev.sencha.com/deploy/ext-4.0.0/docs/guide/tree.html

wcravens
3 May 2011, 4:39 AM
Yes - but this has been part of the problem... if you just change the panel type to tree.Panel without an explicit definition of root: in the TreePanel config then the store will not be initialized correctly. Hence this thread. I'm just posting this as a follow-up so that people don't get caught up in the same three day head scratch that I just did.

e.g. This will not work... but it does demonstrate the 'bug' quite well:


diff --git a/src/ext-4.0.0/examples/app/simple/app/store/Users.js b/src/ext-4.0.
index fbf8f55..c4de03d 100644
--- a/src/ext-4.0.0/examples/app/simple/app/store/Users.js
+++ b/src/ext-4.0.0/examples/app/simple/app/store/Users.js
@@ -1,5 +1,5 @@
Ext.define('AM.store.Users', {
- extend: 'Ext.data.Store',
+ extend: 'Ext.data.TreeStore',
model: 'AM.model.User',
autoLoad: true,

@@ -15,4 +15,4 @@ Ext.define('AM.store.Users', {
successProperty: 'success'
}
}
-});
\ No newline at end of file
+});
diff --git a/src/ext-4.0.0/examples/app/simple/app/view/user/List.js b/src/ext-4
index 731a1d9..7c684fc 100644
--- a/src/ext-4.0.0/examples/app/simple/app/view/user/List.js
+++ b/src/ext-4.0.0/examples/app/simple/app/view/user/List.js
@@ -1,5 +1,5 @@
Ext.define('AM.view.user.List' ,{
- extend: 'Ext.grid.Panel',
+ extend: 'Ext.tree.Panel',
alias : 'widget.userlist',

title : 'All Users',


Note: if you want to try and use the above code make sure that you are pointed at the right sources in simple.html (or edit and rebuild your app distribution files).


diff --git a/src/ext-4.0.0/examples/app/simple/simple.html b/src/ext-4.0.0/examp
index 5dd4e9d..5b62aee 100644
--- a/src/ext-4.0.0/examples/app/simple/simple.html
+++ b/src/ext-4.0.0/examples/app/simple/simple.html
@@ -4,8 +4,7 @@
<title id="page-title">Account Manager</title>

<link rel="stylesheet" type="text/css" href="../../../resources/css/ext-all
- <script type="text/javascript" src="../../../builds/ext-core.js"></script>
- <script type="text/javascript" src="classes.js"></script>
+ <script type="text/javascript" src="../../../ext-debug.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>

bingwei
3 May 2011, 10:14 AM
Hi all,

anyone know how to pass extra params to directFn?


var store = Ext.create('Ext.data.TreeStore', {
proxy: {
type:'direct',
directFn: Category.GetTree,
});
I'd like to pass UserID to Category.GetTree.

Thanks in advance.:)

bregard
10 May 2011, 3:59 AM
Has this been confirmed as a bug? I'm having the same issue. Is there an issue with Loader and StoreManager? My code was working in beta 3 and does not work in 4.0.

hsurya
4 Oct 2011, 5:18 AM
Just to the point: MVC is the answer to develop a constantly expanding web-app.

Folder structure:
-wwwroot
-ExtJS (version 4)
-MyAppName
-app
-controller
-model
-store
-view
-app.js
-default.asp
-get.asp etc

(I deviate from the suggestion to put extJS inside the MyAppName folder, instead I put it in the webroot folder, so that I can test another application without having to copy the whole library. Just use:
<link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all.css">
<script type="text/javascript" src="/extjs/ext.js"></script>

I don't know whether there is any drawback by doing that, but so far it's working allright.

Now the codes. First, this is the old way, non-MVC structure, It is the same as "reorder" example in the package, I modify it a bit.
filename: filetree.asp
(get.asp is the server side code to generate json, use language that you are familiar with)


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
<html>
<title>Filetree example ExtJS4 non-MVC structure</title>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all.css" />
<script type="text/javascript" src="/extjs/ext.js"></script>
<script type="text/javascript">
Ext.BLANK_IMAGE_URL = '/extjs/resources/themes/images/default/tree/s.gif';

Ext.require([
'Ext.Editor',
'Ext.tree.*',
'Ext.data.*',
'Ext.tip.*'
]);

Ext.onReady(function() {
Ext.QuickTips.init();

var store = Ext.create('Ext.data.TreeStore', {
proxy: {
type: 'ajax',
url: 'get.asp'
},
root: {
text: 'My root folder',
id: '',
expanded: true
},
folderSort: true,
sorters: [{
property: 'text',
direction: 'ASC'
}]
});

var tree = Ext.create('Ext.tree.Panel', {
id:'tree',
store: store,
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop'
}
},
renderTo: 'tree-div',
height:400,
width: 300,
title: 'Filetree',
useArrows: true,
listeners: {
itemclick:
function (view, record, item, index, e){
alert('you clicked on '+item.textContent);
}
},
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Expand All',
handler: function(){
tree.expandAll();
}
}, {
text: 'Collapse All',
handler: function(){
tree.collapseAll();
}
}]
}]
});

});

</script>
</head>

<body>
<table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%">
<tr><td align=center>
<table border="0" cellpadding="0" cellspacing="0" width="760">
<tr><td align=left valign=top><br><br><h3>Filetree example ExtJS4 non-MVC structure</h3>
by: hsurya (hasan_surya@yahoo.com)<br><br>
<div style="width:400px;" id="tree-div"></div>
</td></tr>
</table>
</td></tr></table>

</body>
</html>




Next.. the MVC example
filename:default.asp


<html>
<head>
<title>MyApp (Filetree ExtJS4 MVC example)</title>
<link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all.css">
<script type="text/javascript" src="/extjs/ext.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body><div id=filetree-div></div></body>
</html>


filename:app.js


Ext.require([
'Ext.Editor',
'Ext.tree.*',
'Ext.data.*',
'Ext.tip.*'
]);
Ext.BLANK_IMAGE_URL = '/extjs/resources/themes/images/default/tree/s.gif';

Ext.application({
name: 'MyApp',
appFolder: 'app',
controllers: [
'Cfiletree' //I add C here to indicate controller file (to Cfiletree.js)
],


launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: {
xtype: 'MyFiletreeWidget'
//this MyFiletreeWidget we create as an alias in view/filetree/List.js
}
});
}

});




app/controller/Cfiletree.js (I use initial C to name any controller script file, M for model, etc.)


Ext.define('MyApp.controller.Cfiletree', {
extend: 'Ext.app.Controller',

views: [
'filetree.List' //point to app/view/filetree/List.js
],

refs: [
{
ref: 'filetreeRef', //we name it. Can be any name
selector: 'MyFiletreeWidget' //our alias in "app/view/filetree/List.js" --> widget.MyFiletreeWidget
}
],

stores: [
'Sfiletree' //app/store/Sfiletree.js
],
models: ['Mfiletree'], //app/model/Mfiletree.js

init: function() {
this.control({
'MyFiletreeWidget': {
itemclick: this.editNode
},
'MyFiletreeWidget[id=MyFiletree] > toolbar [text="Expand All"]': {
//[id=MyFiletree] is optional (in case you have more than one MyFiletreeWidget?)
click: function(){this.getFiletreeRef().expandAll()}
//filetreeRef in your refs is automatically capitalized to FiletreeRef
}
});
},

editNode: function (view, record, item, index, e) {
alert('you clicked on ' + item.textContent);
//in my real code I use Ext.Editor to edit the node
}
});



app/model/Mfiletree.js


Ext.define('MyApp.model.Mfiletree', {
extend: 'Ext.data.Model',
fields: ['id','text','iconCls','disabled','leaf']
});



app/store/Sfiletree.js


Ext.define('MyApp.store.Sfiletree', {
extend: 'Ext.data.TreeStore',
model: 'MyApp.model.Mfiletree',
autoLoad: true,

proxy: {
type: 'ajax',
url: 'get.asp' //I use asp as server side language. can be .php or .json etc.
},

root: {
text: 'root',
id: '',
expanded: true
},
folderSort: true,
sorters: [{
property: 'text',
direction: 'ASC'
}]
});


app/view/filetree/List.js


Ext.define('MyApp.view.filetree.List' ,{
extend: 'Ext.tree.Panel',
alias : 'widget.MyFiletreeWidget',

id:'MyFiletree',
store: 'Sfiletree',
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop'
}
},
renderTo: 'filetree-div',
height:400,
width: 300,
title: 'Filetree widget',
useArrows: true,
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Expand All' //the listener is placed in controller (Cfiletree.js), made me headache for some time
}, {
text: 'Collapse All',
handler: function(){ //the listener is here directly
this.up('MyFiletreeWidget').collapseAll();
}
}]
}]
});



Working example:

http://hsurya.brinkster.net/filetreeExtjs4

Old Filetree Extjs 2.3.2: http:hsurya.brinkster.net/filetree/

chiqo47
20 Oct 2012, 2:25 PM
I managed to create my mvc treePanel by overwriting a initComponent function on the view. I also needed to specify a root config on this treePanel view (root: {},).


This is a minimal tree-MVC working example i created:
39502
To make it work, just change the paths of extjs files in index.html to your existing paths.


(check the view/FileTree.js)