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!
Related
using extjs 5.1.0
My issues, when I add value to store of grid and then call store.sync()
inserted row become selected (visually) but I cannot select it for edit or darg&drop row for sorting, only helps reload grid.
here is my store:
var store = Ext.create('Ext.data.ArrayStore', {
model: 'pbxe.module.conference.ConferenceModel',
proxy: {
type: 'direct',
api: {
read: pbxe._conference.read,
create: pbxe._conference.create,
update: pbxe._conference.update,
destroy: pbxe._conference.destroy,
},
reader: {
rootProperty: 'data',
totalProperty: 'totalCount',
successProperty: 'success',
messageProperty: 'message'
},
writer: {
writeAllFields: true,
},
},
autoSync: false,
autoLoad: true,
});
We ran into same problem, seems there is an issue of the Selection Model keeping a map of the records added to the store which can't get "deselected".
So with a bit of brute force:
// WORKAROUND for grid / selection model problem
// after adding multiple new records with Store.sync()
//var grid = grid bound to this store...
myStore.sync(
{
scope: this,
success: function (batch, options) {
var sm = grid.getSelectionModel();
var records = batch.operations[0].getRecords();
if (sm && sm.selected)
{ // deselect does not work as has bug leaves new records in map
sm.selected.map = {}; //wipe clear the selected records map
}
sm.select(records);
}
});
Hope this helps - works for us in Ext JS 5.1.0
I dynamically append a child to a tree node. I expect the child node has id, record.id. But I get the generated id from ExtJS.
parent.appendChild({
id : record.id,
text : record.value
});
That is because your are confusing two different concepts. Every tree node has a visual representation and a model behind then, there are two ids: the visual element id and the model id.
You are setting the model id and not the visual element id. Please, take a look at this code:
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: []
}
});
var tree = Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
rootVisible: false,
renderTo: Ext.getBody()
});
var root = tree.getRootNode();
var appendedRecord = root.appendChild({id: 1, text: 'juan'});
alert('component id: ' + appendedRecord.id + ' model id: ' + appendedRecord.get('id'));
Better, take a look at the same code in jsfiddle here and don´t forget press Run
http://jsfiddle.net/HReqT/
Update:
Extjs is who assign the visual element ids, you cannot do it (or at least you shouldn´t do that)
I try to show in a Tree panel a Files System.
I feed my tree with json data and it's work perfectly!
But when I have an empty folder, the tree folder (when it's deploy) show me the complete tree again.
In my server I send a json file which doesn't have children properties.
This is my tree code
Ext.onReady(function () {
var treeStore = Ext.create('Ext.data.TreeStore', {
proxy: {
type: 'ajax',
url: '/File/Tree'
},
root: {
text: 'Files root',
id: 'root',
expanded: true
}
});
var treeUp = Ext.create('Ext.tree.Panel', {
id: 'TreeFileSystem',
title: 'TEST',
useArrows: true,
store: treeStore,
rootVisible: false,
renderTo: 'Tree',
height: 350,
listeners: {
itemClick: function (view, record) {
}
}
});
});
and there is an example of my json code
[
{"cls":"first-level","expanded":"false","children":[
{"cls":"first-level","expanded":"false","children":[
{"leaf":"true","text":"..."},
{"leaf":"true","text":"..."}
],"text":"..."}
],"text":"..."},
{"text":"..."}]
Anybody has an idea for help me?
Thanks!
David
EDIT:
an other example of my JSON
[
{"path":"...","cls":"first-level","expanded":"false","children":[
{"path":"...","cls":"first-level","expanded":"false","children":[
{"path":"...","cls":"first-level","expanded":"false","children":[],"text":"BOBFOLDER1"},
{"path":"...","cls":"first-level","expanded":"false","children":[],"text":"BOBFOLDER2"},
{"path":"...","cls":"first-level","expanded":"false","children":[],"text":"BOBFOLDER3"}
],"text":"BOB"},
{"path":"...","cls":"first-level","expanded":"false","children":[
{"path":"...","expanded":"false","text":"OTHERFOLDER1"}
],"text":"OTHER"}
],"text":"20508322"}]
I explain with that -> BOBFOLDER1, BOBFOLDER2, BOBFOLDER3 contains files and don't have arrow (I can't deploy it and it's the good behaviour).
But OTHERFOLDER1 don't contains files and have an arrow which display root again (same of my picture i give in comments) it's the problem!
the node named OTHER, is shown as a non-leaf node. put "leaf":"true" for the corresponding JSON data.
ie
[
{"cls":"first-level","expanded":"false","children":[
{"cls":"first-level","expanded":"false","children":[
{"leaf":"true","text":"..."},
{"leaf":"true","text":"..."}
],"text":"..."}
],"text":"BOB"},
{"text":"OTHER","leaf":"true"}]
try setting putting loaded: true in all your nodes (or if you use a model config, create field in the model for "loaded" and default it to true.
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 write special combo object to use it as linked combos. Here it is:
comboDivClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel: 'Divisions',
anchor: '95%',
lazyRender:true,
store:new Ext.data.Store({
proxy: proxy,
baseParams:{rfb_type:'divisions'},
reader: divReader,
autoLoad: true
}),
displayField:'div_name',
allowBlank:false,
valueField:'div_id',
triggerAction:'all',
mode:'local',
listeners:{
select:{
fn:function(combo, value) {
if (this.idChildCombo) {
var modelCmp = Ext.getCmp(this.idChildCombo);
modelCmp.setValue('');
modelCmp.getStore().reload({
params: { 'div_id': this.getValue() }
});
}
}
}
},/**/
hiddenName:'div_id',
initComponent: function() {comboDivClass.superclass.initComponent.call(this);}})
As you may see, this combobox load data at child combobox store(which set as idChildCombo).
Ok. Here is how i declare it
new comboDivClass({id:'sub0div',idChildCombo:'sub1div'}),
new comboDivClass({id:'sub1div'})
Yes it works, but it have some odd trouble - it load not only sub1div store, it load at sub0div store too. Why? What im doing wrong?
One thing I see is that you have mode: 'local' config, while it should be remote.
Other thing to consider: Why don't you do it more like this:
var c1 = new comboDivClass({id:'sub0div'});
var c2 = new comboDivClass({id:'sub1div'});
c1.on('select',function(combo, value) {c2.getStore().reload({
params: { 'div_id': c1.getValue() }
})});
ChildCombo.setMasterField( masterField ) {
masterField.on('change', function(field){
this.getStore().filterBy( function(){ //filter by masterFIeld.getValue() } );
})
}
The idea is to link child field to parent not parent to child and this way you can link to any kind form field no only combo.
Here in child combo you have to have store with three columns [group,value,label] where group is value of master field.
This way you can manage to have mode than one master field.