I have a card layout and on card "activate" event I load the store. To keep the store from loading every time that card is activated I check to see if getCount == 0 and if true, I load the store:
handleActivateGrid: function(){
if(this.myTreeGrid().getStore().getCount() == 0){
this.myTreeGrid().getStore().load();
}
I'm using this same approach elsewhere in my code and it works perfectly fine, the only difference is in this case its a Ext.data.TreeStore.
I debugged and getCount() was undefined, even AFTER the store had loaded.
Is there another approach or method I could use to implement the above?
Thanks
EDIT: just checked the docs, getCount() is not a method that exists for Ext.data.TreeStore, so that explains that
A TreeStore consists of a single root node, with child nodes.
To see if there are nodes under the root node, you can use the following
myTreeGrid().getStore().getRootNode().childNodes.length > 0
See http://docs-origin.sencha.com/extjs/4.2.2/#!/api/Ext.data.NodeInterface-property-childNodes
A more correct approach (since a load may not load any child nodes in theory) is to hookup a load event to the store, when it's initially created. From the load handler, you can set your isLoaded flag wherever it's convenient for your code.
Something like http://www.sencha.com/forum/showthread.php?91923-How-to-check-datastore-is-loaded/page2
var storeLoaded = false;
var store = Ext.create('Ext.data.TreeStore', {
proxy: {
type: 'ajax',
url: 'get-nodes.php'
},
root: {text: 'Ext JS',id: 'src', expanded: true},
listeners: {
load: function() {
storeLoaded = true;
}
}
});
var tree = Ext.create('Ext.tree.Panel', {
store: store,
renderTo: 'tree-div',
height: 300,
width: 250,
title: 'Files'
});
Just tried this code .
myTreeGrid().getStore().getRootNode().getChildAt(0) == undefined
UPDATE -
I HAVE ALSO MADE A MOCK IN JSFIDDLE http://jsfiddle.net/mAgfU/371/
AND WITH A FORM PANEL : http://jsfiddle.net/kA6mD/2/
I have the bellow comboox.
When I use the following code to set the form values:
this.form.loadRecord(data);
the entire form is acting ok except from the combo.
instead of giving me the displayField, I get the valueField in the display.
As you can see in the image above, the combo should show the word "Walla" (displayField) instead of "1" (valueField)
Ext.define('App.view.ForeignCombo', {
extend: 'Ext.form.ComboBox',
alias: 'widget.foreigncombo',
queryMode: 'local',
displayField: 'Name',
valueField: 'Id',
editable: false,
matchFieldWidth: false,
constructor: function(config) {
Ext.apply(this, config);
Ext.define('BrnadComboModel', {
extend: 'Ext.data.Model',
fields: ['Id', 'Name']
});
this.store = Ext.create('Ext.data.Store', {
model: 'BrnadComboModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/api/Brand/',
reader: {
type: 'json',
root: 'Results'
}
},
pageSize: 50,
});
this.callParent();
}
}
);
this is how I use it:
{
"xtype": 'foreigncombo'
, "name": 'Brand.Id'
, "fieldLabel": 'Brand.Id'
}
There is no race bewtween the form display and the combo ajax request, the combo store is autoLoad:true, meaning I see that it has already been loaded...
Thanks
I used your fiddle a an example. Place a breakpoint in line 87 (Ext.ComponentQuery.query('comobobox')....), in this fiddle http://jsfiddle.net/kA6mD/9/, and set a watch to Ext.ComponentQuery.query('combobox')[0].store.data.. you'll notice the store has no data. This may be linked to what I mentioned in the comment.
I know there must be a better way of doing this, but what I usually use as a workaround is either load the store at some point before in the app or use a synchronous Ext.Ajax.request and load each record at a time in the store.
As this is a combo for brands I suppose you could load the store before (i.e. app load) and lookup for the store instead of creating a new one each time you create a foreigncombo component, so the first solution should work.
As for the second workaround it should also work, it takes a little bit more coding but its actually pretty easy. It should look something like this...
Ext.Ajax.request({
url:'your/url/',
async:false,
.....
success:function(response){
var records = Ext.JSON.decode(response.responseText);
for(var m=0; m<records.length; m++){
var record = Ext.create('YourBrandModel',{
abbr:records[m].abbr,
name:records[m].name
});
store.add(record);
}
}
})
You should do this as few times as possible as it may slow down the user experience if it gets called everytime you create a "foreigncombo", so checking if this store exists before creating one might be a good idea.
Please take in cosideration that I have not tested this code, so you may have to tweak it a little in order for it to work. But it should get you on tracks.
I have a map with couple of layers and I want to have each layer in separate folder below the root.
http://jsfiddle.net/WGSQb/
I'm creating regular store and I have no idea how to alter the code to match my need (pics below):
var store = Ext.create('Ext.data.TreeStore', {
model: "GeoExt.data.LayerTreeModel",
root: {
expanded: true,
children: [{
plugins: ['gx_overlaylayercontainer'],
expanded: true
}]
}
});
Here it how it looks now :
Here it what I want to accomplish (without using photoshop :) ) :
Am working on moving nodes in a tree, and as they are moved, their ID's are updated in the database through C# in the back-end. Till now, i have managed to update the position of the node that is being moved, but after its moved, the position of the other nodes in the tree should also get updated. Could anyone tell me how to proceed with this?
itemmove : {
fn : function(v, oldParent, newParent, index, eOpts) {
var nodeID = v.data.id;
var oldParent = oldParent.data.id;
var newParent = newParent.data.id;
var index = index;
var level = v.data.level;
movenode(nodeID, oldParent, newParent, index, level);
}
}
function movenode(nodeID, oldParent, newParent, index, level) {
Ext.Ajax.request({
url : 'data/pages.aspx',
params : {
UserID : USER.UserID,
mode : 'MOVENODE',
currentNode : nodeID,
oldParentNode : oldParent,
newParentNode : newParent,
index : index,
level : level,
ProjDB : projDB
},
success : function() {
loadTREEst();
genMessage(LANG.Suc, LANG.SaveOK, 'tick', false);
},
failure : function() {
genMessage(LANG.Warn, LANG.GenWarn, 'warn', false);
}
});
}
So, i send the parameters to SQl, and then update the index of the node that has been moved.
For example, if i move a node from position 8 to 1, the index of the 8th node changes to 1 in the database, but the index of the first node remains at 1. And because of this, the tree also doesnt get updated. i want all the other nodes in the tree to get updated as well. So, in this case, the node in index 1 will become index 2, the node in index 2 will become index 3, and so on. Can anyone explain me how to do this.
Is there any other method other than autosync or sync to do this?
Thanks in advance.
Here is some sample code that works with 4.1:
Ext.define('BS.model.ItemCategory', {
extend: 'Ext.data.Model',
fields: [
{name: 'name' , type: 'string'},
{name: 'iconCls' , type: 'string', defaultValue: 'treenode-no-icon'},
{name: 'leaf' , type: 'boolean', defaultValue: false},
{name: 'expanded' , type: 'boolean', defaultValue: true, persist: false},
{name: 'index' , type: 'int'},
],
proxy: {
type: 'direct',
api: {
create: ItemCategories.Create,
read: ItemCategories.Read,
update: ItemCategories.Update,
destroy: ItemCategories.Delete,
},
},
});
You won't be having a direct proxy as your server isn't php, but just put the corresponding server scripts (see docs).
Then my store:
Ext.define('BS.store.ItemCategories', {
extend: 'Ext.data.TreeStore',
model: 'BS.model.ItemCategory',
autoSync: true,
root: {
text: 'Root',
id: 'NULL',
expanded: true
},
clearOnLoad: true,
});
And the view:
Ext.define('BS.view.admin.pages.item-categories.ItemCategories' ,
{
extend: 'Ext.tree.Panel',
alias : 'widget.item-categories-tree',
store: 'ItemCategories',
displayField: 'name',
rootVisible: false,
useArrows: true,
multiSelect: false,
singleExpand: false,
allowDeselect: true,
plugins: {
ptype: 'treeviewdragdrop',
},
});
That's pretty much it! When you move a node you'll see ExtJS sends an update request to the server with an array of all the nodes whose index (sort) has changed.
This is the code I had for 4.0.7, to my memory it solved this problem.
// This happens after drag and drop
onItemMove: function(aNode, aOldParent, aNewParent, aIndex, aOptions)
{
// Update the indeces of all the parent children (not just the one that moved)
for ( i = 0; i < aNewParent.childNodes.length; i++ )
{
aNewParent.childNodes[i].data.sort = i;
aNewParent.childNodes[i].setDirty();
}
this.mStore.sync();
},
Notice that you won't have mStore.sync() as you are sending your own request to the server, which only involves one record. By setting child nodes as dirty, sync sends more than one record to the server's update call (in my case, I'm using autosync and direct).
You should consider what happens when the user moves a node from a parent node to the parent's sibling - the index (sort) of some nodes in both the old and new parent will change. So you might end up with 6 records that need updating on the server.
All I'm saying is that given 4.1 already handles node moving correctly, you might be better off upgrading to 4.1 and take advantage of the native support for this than coding it yourself. If you stick to 4.0.7, just remember to consider that a moving a node could require the updating of many nodes.
I'm using Extjs4 treepanel with Json data.I want reload the treepanel and need expand tree menu to specified node.
I'm using the following code. Please let me know how do this.
//Define tree store
var store = Ext.create('Ext.data.TreeStore', {
proxy: {
type: 'ajax',
url: 'my_tree.php',
},
noCache: false
});
// Treepanel
var treePanel = Ext.create('Ext.tree.Panel', {
id: 'mytree',
renderTo: 'tree_div',
height: 400,
bodyBorder: false,
border: false,
singleExpand: true,
rootVisible: false,
store: store,
useArrows: true
});
//Reload tree
function reload_tree(){
var tree_panel = Ext.getCmp('mytree');
tree_panel.enable();
tree_panel.getLoader().dataUrl = 'my_tree.php';
tree_panel.getLoader().load(tree_panel.root);
//Expand tree node
tree_panel.getLoader().on('load', function(loader, node){
tree_panel.getNodeById(nodeid).expand();
//here node id is tree menu nodeid
});
}
Thanks in advance
Reload the tree i think it's simpler to just call
treePanel.getStore().load();
then you can listen to the load event, so that the data is all fetched and finally from there select the desired node.
treePanel.on("load", function( treeStore, records, successful, operation)){
var id = 4; // This is the ID of the node that somehow you know in advance
var node = treeStore.getNodeById(id);
treePanel.expandPath(node.getPath());
});
HTH!