Why I rootNode.findChild returns null - extjs

I have a tree panel. Firebug shows that I have three children under root node. However, when I do rootNode.findChild in my controller, it always returns null. What am I missing?
Here is my controller:
Ext.define("GiipIq.controller.Problems", {
extend: "Ext.app.Controller",
refs: [{selector: '#problemsTree', ref: 'problemsTree'}],
selectFirstProblem: function() {
**var problemsTree = this.getProblemsTree();
var rootNode = problemsTree.getStore().getRootNode();
console.log(rootNode); <== I can see three child nodes under root node in firebug
var record = rootNode.findChild("id", "bit-manipulation", true);
console.log(record);**
//problemsTree.getSelectionModel().select(record); **<== select(index) does not work either**
},
init: function () {
this.control({
"#problemsTree": { afterrender: this.selectFirstProblem }
});
}
});
Here is Firebug result:
0
Object { raw={...}, modified={...}, data={...}, more...}
1
Object { raw={...}, modified={...}, data={...}, more...}
2
Object { raw={...}, modified={...}, data={...}, more...}
Here is the detail of the first one:
0
Object { raw={...}, modified={...}, data={...}, more...}
$className
"GiipIq.model.Problem"
$hasInheritableStatics
Object { setProxy=true, getProxy=true, setFields=true, more...}
$inheritableStatics
["setProxy", "getProxy", "setFields", 2 more...]
_singleProp
Object {}
alternateClassName
"Ext.data.Record"
associations
Object { allowFunctions=false, initialConfig={...}, items=[0], more...}
childNodes
[Object { raw={...}, modified={...}, data={...}, more...}, Object { raw={...}, modified={...}, data={...}, more...}]
clientIdProperty
null
config
Object {}
configMap
Object {}
data
Object { id="algorithm", text="algorithms", leaf=false, more...}
Here is my view:
Ext.define("GiipIq.view.Problem", {
extend: "Ext.window.Window",
alias: "widget.problemwindow",
titleAlign: "center",
closable: false,
layout: "border",
autoShow: true,
maximizable: true,
draggable: false,
resizable: false,
x: 0,
y: 0,
width: Ext.getBody().getViewSize().width/2,
height: Ext.getBody().getViewSize().height/2,
id: "problem-window",
getEastPanel: function() {
return {
region: "west",
xtype: "treepanel",
title: "Problems",
width: 200,
split: true,
collapsible: false,
floatable: false,
rootVisible: false,
useArrows: true,
store: Ext.create("GiipIq.store.Problems"),
id: "problemsTree",
dockedItems: [{
xtype: "toolbar",
dock: "bottom",
layout: "fit",
items: [{
xtype: "button",
text: 'Click to Run Selected Problems',
id: "run-problems-button"
}]
}],
listeners: {
checkchange: function(node, checkedStatus, options) {
console.log("vp");
}
}
};
},
getCentralPanel: function() {
return {
xtype: "tabpanel",
width: (Ext.getBody().getViewSize()/2) - 200,
bodyBorder: false,
items: [{
title: "Problem Description",
id: "problem-description-tab"
},{
xtype: "panel",
title: "Source Code",
},{
xtype: "panel",
title: "Big O Analysis",
}]
};
},
initComponent: function () {
this.items = [
this.getEastPanel(),
this.getCentralPanel()
];
this.callParent(arguments);
}
});
Here is my json data:
{
success: true,
children: [{
id: "algorithm",
text: "algorithms",
expanded: true,
leaf: false,
checked: false,
children: [
{ id: "bit-manipulation", text: "bit manipulation", leaf: true, checked: true },
{ id: "brain-teaser", text: "brain teaser", leaf: true, checked: true }
]
},{
id: "data-structure",
text: "data structures",
expanded: true,
checked: false,
leaf: false,
children: [
{ id: "array-and-string", text: "array and strings", leaf: true, checked: true },
{ id: "linked-list", text: "linked lists", leaf: true, checked: false}
]
},{
id: "knowledge-based",
text: "knowledge based",
expanded: true,
leaf: false,
checked: false,
children: [
{ text: "C and C++", leaf: true, checked: false},
{ text: "Java", leaf: true, checked: false}
]
}]
}

There is no apparent problem in the code you posted, anyway some hints:
If the tree is asynchronously loaded, the child may not be there at the time you try to find it
You can stop your code and step into the findChild method to see what's happening there and why null is returned
You can try to call findChild from console. If it works from there then it is a timing problem so your code is too early.

Related

ExtJS 4.1 treepanel - expanding a treepanel is resulting in duplicate records

I am using ExtJS 4.1. I have a TreePanel which I bind to one of two TreeStore. After I rebind a store & expand collapse nodes, records are getting duplicate & I see error Uncaught TypeError: Cannot read property 'internalId' of undefined
Another issue is, I am only able to bind store once. When i call treePanel.setRootNode() second time it does not work (irrespective of whether I expand the nodes or not).
Look at this fiddle
Here is the code:
var sportsStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
id: 133,
children: [{
text: "Audi",
id: 1,
leaf: true
},
{
text: "sports cars",
expanded: true,
id: 2,
children: [{
id: 3,
text: "Porsche",
leaf: true
},
{
text: "Mustang",
id: 4,
leaf: true
}
]
},
{
text: "Jaguar",
id: 5,
leaf: true
}
]
}
});
var carStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
id: 1444,
children: [{
id: 6,
text: "Toyota",
leaf: true
},
{
text: "cars",
id: 7,
expanded: true,
children: [{
id: 8,
text: "honda",
leaf: true
},
{
text: "Nissan",
id: 9,
leaf: true
}
]
},
{
text: "Kia",
id: 10,
leaf: true
}
]
}
});
Ext.create('Ext.panel.Panel', {
title: 'Car Simple Tree',
width: 300,
height: 450,
renderTo: Ext.getBody(),
items: [{
xtype: 'button',
text: 'sports',
handler: function() {
alert('You clicked the sports button!');
var t = Ext.getCmp('tp');
t.setRootNode(sportsStore.getRootNode());
}
},
{
xtype: 'button',
text: 'car',
handler: function() {
alert('You clicked the car button!');
var t = Ext.getCmp('tp');
t.setRootNode(carStore.getRootNode());
}
},
{
xtype: 'treepanel',
id: 'tp',
store: sportsStore,
rootVisible: false,
lines: true
}
]
});
Just for the record you know your problem is solved in one line in 6.0 with just calling setStore() and passing as parameter the store you want right?
Here is a demo of this working in 6.0.
I played with this for a good amount of time and although my Sencha is somewhat rusty (used to be a big fan back in the day) I managed to get something working.
Now it might not be your cup of tea but it does exactly what you want ... you change the stores and expanding/collapsing works etc. The trick is I dynamically re-create the tree on every store change and set the store as the default store to that new tree. The decommissioned trees are removed by Ext.destroy etc.
Here is that Ext 4.1 working example in Fiddle
And here is the code for your reference:
Ext.define('Thing', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'text',
type: 'string'
}]
});
var sportsStore = Ext.create('Ext.data.TreeStore', {
model: 'Thing',
storeId: 'sportsStore',
clearOnLoad: true,
root: {
expanded: true,
id: 133,
children: [{
text: "Audi",
id: 1,
leaf: true
}, {
text: "sports cars",
expanded: true,
id: 2,
children: [{
id: 3,
text: "Porsche",
leaf: true
}, {
text: "Mustang",
id: 4,
leaf: true
}]
}, {
text: "Jaguar",
id: 5,
leaf: true
}]
}
});
var carStore = Ext.create('Ext.data.TreeStore', {
model: 'Thing',
storeId: 'carStore',
clearOnLoad: true,
root: {
expanded: true,
id: 1444,
children: [{
id: 6,
text: "Toyota",
leaf: true
}, {
text: "cars",
id: 7,
expanded: true,
children: [{
id: 8,
text: "honda",
leaf: true
}, {
text: "Nissan",
id: 9,
leaf: true
}]
}, {
text: "Kia",
id: 10,
leaf: true
}]
}
});
// This function does the magic by removing/then destroying the old tree and
// adding the newly created one with default new store setup
function setupTree(storeName) {
var pnl = Ext.getCmp('pnl');
var treePanel = Ext.getCmp('tp')
if (treePanel) {
pnl.remove(treePanel)
Ext.destroy(treePanel)
}
pnl.add(new Ext.create('Ext.tree.Panel', {
id: 'tp',
autoRender: true,
rootVisible: false,
store: storeName,
animate: false,
lines: true
}))
}
Ext.create('Ext.panel.Panel', {
id: 'pnl',
title: 'Car Simple Tree',
width: 300,
height: 450,
renderTo: Ext.getBody('#canvas'),
items: [{
xtype: 'button',
text: 'sports',
handler: function() {
setupTree('sportsStore')
}
}, {
xtype: 'button',
text: 'car',
handler: function() {
setupTree('carStore')
}
}],
listeners: {
afterrender: function(self) {
setupTree('sportsStore')
}
}
});
I also added ids to the stored as well as defined a model for the stores just to be more close to best practices etc.
The thing that makes this move is the setupTree function which looks for a tree with certain id, if it finds it cleans it and then creates a new one with a default store the one we clicked on.
Hope this helps.
I suggest the following approach, which may be a workaround, but ExtJS 4.1 version has some issues in UpdateIndexes() method:
define an empty tree store (baseStore) and bind it to the tree panel
on every button click, fill this empty store with data from appropriate store.
Code:
Ext.onReady(function(){
Ext.QuickTips.init();
Ext.FocusManager.enable();
// Stores
var baseStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
leaf: false,
children: []
}
});
var sportsStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
id: 133,
children: [
{
text: "Audi",
id: 1,
leaf: true
},
{
text: "sports cars",
expanded: true,
id: 2,
children: [{
id: 3,
text: "Porsche",
leaf: true
},
{
text: "Mustang",
id: 4,
leaf: true
}
]
},
{
text: "Jaguar",
id: 5,
leaf: true
}
]
}
});
var carStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
id: 1444,
children: [
{
id: 6,
text: "Toyota",
leaf: true
},
{
text: "cars",
id: 7,
expanded: true,
children: [
{
id: 8,
text: "honda",
leaf: true
},
{
text: "Nissan",
id: 9,
leaf: true
}
]
},
{
text: "Kia",
id: 10,
leaf: true
}
]
}
});
// Filling data
function fillStore(xparent, xnode) {
for (var i = 0; i < xnode.childNodes.length; i++) {
var current = xnode.childNodes[i];
var added = xparent.appendChild(
{
text: current.data.text,
leaf: current.data.leaf,
id: current.data.id
}
);
if (current.data.leaf === false) {
fillStore(added, current);
}
}
}
function setStore(store) {
var root = baseStore.getRootNode();
if (root.hasChildNodes()) {
root.removeAll();
}
fillStore(root, store.getRootNode());
}
// First fill
setStore(carStore);
Ext.create('Ext.panel.Panel', {
title: 'Car Simple Tree',
width: 300,
height: 450,
renderTo: Ext.getBody(),
items: [
{
xtype: 'button',
text: 'sports',
handler: function() {
alert('You clicked the sports button!');
var t = Ext.getCmp('tp');
setStore(sportsStore);
}
},
{
xtype: 'button',
text: 'car',
handler: function() {
alert('You clicked the car button!');
var t = Ext.getCmp('tp');
setStore(carStore);
}
},
{
xtype: 'treepanel',
id: 'tp',
store: baseStore,
rootVisible: false,
lines: true
}
]
});
});
Notes:
Working fiddle can be found here.

ExtJS6: Second instance of TreeStore has no grandchildren

ExtJS6: Second instance of TreeStore has no grandchildren.
I have a class, MyStore, which inherits from TreeStore.
Then, I created an instance of MyStore to be displayed in a treepanel.
So far so good.
Then, I created another instance of MyStore to be displayed in another treepanel.
Here comes the problem: the second treepanel does not have grandchild. All it has are it's root node and it's root node's children.
How do I code this so that the 2nd (and succeeding) instance of TreeStore will have grandchildren?
https://fiddle.sencha.com/#fiddle/1ehq
Ext.define('MyStore',{
extend: 'Ext.data.TreeStore',
root: {
expanded: true,
text: 'This is the root node',
children: [
{
text: 'Food',
expanded: true,
children: [
{
text: 'Cake',
leaf: true
},
{
text: 'Ice cream',
leaf: true
}
]
},
{
text: 'Toys',
expanded: true,
children: [
{
text: 'Ball',
leaf: true
},
{
text: 'Bat',
leaf: true
}
]
}
]
}
});
Ext.widget('treepanel',{
title: 'first tree panel',
renderTo: Ext.getBody(),
store: new MyStore()
});
Ext.widget('treepanel',{
title: 'second tree panel',
renderTo: Ext.getBody(),
store: new MyStore()
});
Ext.widget('panel', {
html: 'What happend to the "Food" and "Toys" of the second tree panel? Why did they loose their children?',
renderTo: Ext.getBody(),
});
Use this Fiddle:https://fiddle.sencha.com/#fiddle/1hti
Ext.define('MyStore',{
extend: 'Ext.data.TreeStore'
});
var store1 = Ext.create('MyStore',{
extend: 'Ext.data.TreeStore',
root: {
expanded: true,
text: 'This is the root node',
children: [
{
text: 'Food',
expanded: true,
children: [
{
text: 'Cake',
leaf: true
},
{
text: 'Ice cream',
leaf: true
}
]
},
{
text: 'Toys',
expanded: true,
children: [
{
text: 'Ball',
leaf: true
},
{
text: 'Bat',
leaf: true
}
]
}
]
}
});
var store2 = Ext.create('MyStore',{
extend: 'Ext.data.TreeStore',
root: {
expanded: true,
text: 'This is the root node',
children: [
{
text: 'Food',
expanded: true,
children: [
{
text: 'Cake',
leaf: true
},
{
text: 'Ice cream',
leaf: true
}
]
},
{
text: 'Toys',
expanded: true,
children: [
{
text: 'Ball',
leaf: true
},
{
text: 'Bat',
leaf: true
}
]
}
]
}
});
Ext.widget('treepanel',{
title: 'first tree panel',
renderTo: Ext.getBody(),
store: store1
});
Ext.widget('treepanel',{
title: 'second tree panel',
renderTo: Ext.getBody(),
store: store2
});
Ext.widget('panel', {
html: 'What happend to the "Food" and "Toys" of the second tree panel? Why did they loose their children?',
renderTo: Ext.getBody(),
});

For Ext.tree.Panel nodes, arrow button is not displayed, even though useArrow property is used

For Ext.tree.Panel nodes, arrow button is not displayed, even though useArrow property is used. While doing moveover the left of the nodes, pointer is displaying, but the visibility of arrow is false.
How can I solve this issue ??
Giving below the code, I used.
Ext.create('Ext.tree.Panel', {
useArrows: true,
autoScroll: false,
animate: true,
enableDD: false,
title: 'Configuration',
width: 200,
height: 150,
rootVisible: false,
store: [{
root: {
expanded: true,
children: [{
text: "Configure Application",
expanded: true,
children: [{
text: "Manage Application",
leaf: true
}, {
text: "Scenario",
leaf: true
}]
}, {
text: "User Configuration",
expanded: true,
children: [{
text: "Manage User",
leaf: true
}, {
text: "User rights",
leaf: true
}]
}, {
text: "Test Configuration",
leaf: true,
children: [{
text: "Manage User",
leaf: true
}, {
text: "User rights",
leaf: true
}]
}]
}
}]
});
Attaching the screenshot of the UI tree.
]
I am using extjs-4.2.2
I changed your store definition and now it shows arrows as expected if useArrows property is set to true in config json.
You can try that in sencha fiddle.
var root = {
expanded: true,
children: [{
text: "Configure Application",
expanded: true,
children: [{
text: "Manage Application",
leaf: true
}, {
text: "Scenario",
leaf: true
}]
}, {
text: "User Configuration",
expanded: true,
children: [{
text: "Manage User",
leaf: true
}, {
text: "User rights",
leaf: true
}]
}, {
text: "Test Configuration",
leaf: true,
children: [{
text: "Manage User",
leaf: true
}, {
text: "User rights",
leaf: true
}]
}]
};
Ext.application({
name: 'Fiddle',
launch: function() {
Ext.create('Ext.tree.Panel', {
useArrows: true,
autoScroll: false,
animate: true,
enableDD: false,
title: 'Configuration',
width: 400,
height: 400,
renderTo: Ext.getBody(),
rootVisible: false,
store: Ext.create('Ext.data.TreeStore', {
root: root
})
});
}
});

selecting node when using treeStore ExtJS (proxy solution)

I have tree store.
var store = Ext.create('Ext.data.TreeStore', {
root: {
autoLoad:false,
expanded: false,
children: [
{
id:"0", text: "School Friends", expanded: true, children:
[
{
id:"1", text: "Mike", leaf: true, name: "Mike", email: "mike#stackoverflow.com", phone: "345-2222"
},
{
id:"select", text: "Laura", leaf: true, name: "Laura", email: "laura#stackoverflow.com", phone: "345-3333"
}
]
}
]
}
});
and Tree panel.
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
rootVisible: false,
renderTo: Ext.getBody(),
listeners:{
afterrender:function(){
var record = this.getStore().getNodeById('1');
this.getSelectionModel().select(record)
}
}
});
everything works! but when I change store, using proxy request. Selection is n*ot working*
var storeTree = Ext.create('Ext.data.TreeStore', {
autoLoad:true,
expanded: true,
proxy: {
type: 'ajax',
url: 'tree.json',
},
root: {
text: 'Ext JS',
id: 'src',
expanded: true,
// children:[]
},
folderSort: true,
sorters: [{
property: 'text',
direction: 'ASC'
}]
});
I use same JSON
[
{"id":4, "text":"second",},
{
id:"0", text: "School Friends", expanded: true, children:
[
{
id:"1", text: "Mike", leaf: true, name: "Mike", email: "mike#stackoverflow.com", phone: "345-2222"
},
{
id:"select", text: "Laura", leaf: true, name: "Laura", email: "laura#stackoverflow.com", phone: "345-3333"
}
]
},
]
for example one solution:
var storeTree = Ext.create('Ext.data.TreeStore', {
autoLoad:false,
expanded: false,
proxy: {
type: 'ajax',
url: 'tree2.json',
extraParams: {o: 'SELECTED'},
},
root: {
text: 'Ext JS',
id: 'src',
expanded: true,
children:[]
},
folderSort: true,
sorters: [{
property: 'text',
direction: 'ASC'
}]
});
storeTree.load({
url: 'tree.json'
});
storeTree.on({
'load': function(store) {
var node = store.getNodeById("select"); // your id here
treePanel.getSelectionModel().select([node]);
treePanel.selectPath(node.getPath());
},
single: true
});

Click event on tree's children/node

I really confused by ExtJs tree object, something is wrong with my code but I don't know what.
Consider I have this code:
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{ text: "detention", leaf: true },
{ text: "homework", expanded: true, children: [
{ text: "book report", leaf: true },
{ text: "alegrbra", leaf: true}
] },
{ text: "buy lottery tickets", leaf: true }
]
}
});
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
rootVisible: false,
renderTo: Ext.getBody()
});
How can I bind a click event to my tree's children/leaf?
Like so?
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{ text: "detention", leaf: true },
{ text: "homework", expanded: true, children: [
{ text: "book report", leaf: true },
{ text: "alegrbra", leaf: true}
] },
{ text: "buy lottery tickets", leaf: true }
]
}
});
Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 200,
height: 150,
store: store,
rootVisible: false,
renderTo: Ext.getBody(),
listeners: {
itemclick: function(s,r) {
alert(r.data.text);
}
}
});
see this JSFiddle

Resources