I have treestore, i want to traverse the each node. I found no each function in the treestore. But the store have the each function. I also tried the treestore.data. but not success.
pls help me .tks!
Ext.data.TreeStore has no each method, since it deals with Ext.data.Tree. However, Ext.data.NodeInterface has eachChild method, you can use this method to traverse the tree.
function traverse(node) {
// do something with node
node.eachChild(function(child) {
traverse(child); // handle the child recursively
});
}
traverse(yourTreeStore.getRootNode()); // start tree traversal with root node
Use Ext.each as bellow:
Ext.each(tree.getRootNode().childNodes, function (node) {
console.log(node.data.text);
});
Why can't you use Ext.Array.each for your requirement....
Refer below sample example.
Ext.Array.each(records, function(record, index, records) {
if(!(record.get('name')==='')){
}
});
Related
I am new to angular-tree-widget.js. We need to implement double click event once we click on any tree child node. All I found only two events are supported.
$scope.$on('selection-changed', function (e, node) {
//node - selected node in tree
$scope.selectedNode = node;
});
$scope.$on('expanded-state-changed', function (e, node) {
// node - the node on which the expanded state changed
// to see the current state check the expanded property
//console.log(node.expanded);
$scope.exapndedNode = node;
});
How do I add double click event on a node here? Please help me. Thanks in advance.
You can add ng-dblclick, as #Manikandan suggested, in the following way:
HTML
<body ng-controller="TreeController" ng-dblclick="dblclick($event)">
<tree nodes='treeFamily'></tree>
</body>
JavaScript
controller('TreeController', ['$scope', function ($scope) {
$scope.dblclick = function(evt) {
angular.element(evt.target).toggleClass('red')
}
...
}])
Live Demo
https://plnkr.co/edit/nWfiDA82WDpgRGnLqJUs?p=preview
As you can see, the idea is to subscribe to event on parent element of the tree and distinguish between tree items using evt.target, which is passed to event handler using angular's $event
I use Extjs 3.4. I am working on TreePanel with checkbox solution.
What I need is: When I check father node, all childNodes also checked. It's easy, but it depends on extjs expand all childNodes.
If I do
tree.expandAll();
tree.collapseAll();
My check strategy will work, but I don't want the expand effect.
My extjs code(checkchange event) is something like the following:
var checkchange = function(node, flag) {
if (node.hasChildNodes()) {
node.cascade(function(node) {
node.attributes.checked = flag;
node.ui.checkbox.checked = flag;
return true;
});
}
var pNode = node.parentNode;
for (; pNode != null; pNode = pNode.parentNode) {
if (flag || tree.getChecked("checked", pNode).length - 1 == 0) {
pNode.attributes.checked = flag;
pNode.ui.checkbox.checked = flag;
}
}
};
var tree = new Ext.tree.TreePanel({
listeners: {
'checkchange': checkchange
},
})
How can I do? Thank every one for giving advice.
[ EDIT ]
I create A Demo In jsfiddle, that can be easily test.
(Since Extjs 3.4.0 cdn used by jsfiddle not work, I append another cdn extjs resource from https://cdnjs.com/libraries/extjs/3.4.1-1)
I am not sure whether you really want the whole tree to be loaded node by node when checking the root node. I would recommend to lazily check the child nodes when they are loaded for an already-checked parent node, by attaching to the load event. Something like this:
load:function(me, node) {
if(node && node.attributes.checked) node.cascade(
... [function to check all children]
)
}
Depending on your intentions for further processing and your tree size, this could be better than expanding the whole tree to render and check all checkboxes.
If you want the tree to be loaded directly, I would recommend to use preloadChildren:true on the TreeLoader. This is easier than a manual implementation of cascaded load.
I didn't really solve this problem. But I got an eclectic solution.
Only expand when needed
checkchange : function(node, flag){
node.cascade(function(node) {
// when you check, first expand, then child nodes can be checked too
if(node.expanded == false)
node.expand(true);
node.attributes.checked = flag;
node.ui.checkbox.checked = flag;
return true;
});
......
}
This will meet the precondition that all child nodes should have expanded. But also no need expanded when first loaded.
If a parent node checked when first loaded, all child nodes need to be expand
this.treeLoader = new Ext.tree.TreeLoader({
url : 'xxx',
baseParams : {
someparam: ""
},
listeners : {
'load' : function(tree,node,response) {
var res = Ext.util.JSON.decode(response.responseText);
if(res.success != undefined && !res.success) {
Ext.Msg.alert('Hint', res.message);
return;
}
node.cascade(function(node) {
if(node.attributes.checked == true) {
node.expand(true);
}
});
},
}
});
This two methods does solve my prolem though not very perfect.
Hope this can help others.
I saw this question and I want to go a step further
https://stackoverflow.com/questions/18606212/store-filter-in-sencha-touch#=
First I filter that table (this is working so far):
Then I will filter another table depending on the filter of the first table.
Result will be either:
or (for example):
And now I tested something like:
TABLEVIEWSTORE1.filter("name", name);
TABLEVIEWSTORE1.load({callback: function (){
tableviewstore2.load({callback: function (){
TABLEVIEWSTORE1.each(function(item){
tableviewstore2.filterBy(function(record,id){
return record.get("number") == item.get("number");
}, this);
});
TABLEVIEWSTORE1.load({callback: function (){
tableviewstore2.load({callback: function (){
// DO MORE THINGS
}});
}});
}});
}});
});
Has anyone an idea how it can be working properly?
Firstly we should find all the unique numbers from the first filtered store.
Then, we should filter the second store based on those unique numbers array.
We will use Ext.Array for this.
var uniqueNumbers= [];
TABLEVIEWSTORE1.each(function(item){
Ext.Array.include(uniqueNumbers,item);
});
tableviewstore2.filterBy(function(record){
return Ext.Array.contains(uniqueNumbers,record.get("number"));
});
I have some data that I'm getting from the server that depending on the situation may bring different fields, so what I have is this:
//This is the way i'm attaching the newly created template to the view
//Still no success
function processDataMethod(response){
//some processing here...
var details = Ext.widget('details');
details.config.itemTpl = new Ext.XTemplate(tplFields);
}
Ext.Ajax.request({
url: '...',
...,
success: function (response, request) {
var combinedData = processDataMethod(response);
operation.setResultSet(Ext.create('Ext.data.ResultSet', {
records: combinedData,
total: combinedData.length
}));
operation.setSuccessful();
operation.setCompleted();
if (typeof callback == "function") {
callback.call(scope || that, operation);
currentList.up().push(Ext.widget('details'));
}
}
});
Any help is appreciated, thanks!!
You have to make a distinction between a number of things:
currentList.up() returns a DOM element (Ext.dom.Element). This has no method push().
With Ext.widget('details', config); you can pass a config like {itemTpl: yourTemplate, data: yourData} to create an instance with a custom template and custom data.
To update your component after creation you can always do someWidget.update(data);.
A component can be rendered to an HTML element with the renderTo option.
A component can be appended to existing components in different ways and you can update the whole layout or parts of it in different ways. This is unnecessary if you are rendering to an HTML element.
Does that help you find your problem?
I am testing my ExtJs App with Jasmine. So there are no views involved.
I want to expand several nodes, but first my root node. But even expanding that node fails.
I create my TreeStore, then:
Code:
// oStore is my treestore, everything OK
// Here, I also tried calling oStore.load(); see below
var oNode = oStore.getNodeById( 'root' );
// oNode.isExpanded() says false
// oNode.hasChildNodes() says false
oNode.expand(false, function(oChildren) {
// it never gets here
console.log( "hello?");
});
My listener for load gets called, but the listener for beforeexpand does not get called.
If I call oStore.load() at the beginning after store creation, then when the on load listener gets called it says, oNode.childNodes.length has 3 children...
So why is expand()'s callback not called? How can I get that node to expand?
Why are the children of the node already loaded when calling oStore.load()? After that expand() is also not fired.
EDIT:
Starting my root node with expanded: true makes my store collapse correctly on collapse(), but after it expand() does nothing.
oNode.collapse(false, function() {
console.log( "collapse()" ); // works, but expand() afterwards does not
});
Found the solution. I need to wait for the store to get loaded. Is is a Jasmine issue:
runs( function() {
oStore.on( 'load', function() {
bStoreLoaded = true;
});
});
waitsFor( function() {
return bStoreLoaded;
}, " store to be loaded", 5000 );
runs( function() {
oNode.expand(false, function( aoChildren ) {
aoChildrenRoot = aoChildren;
bRootExpanded = true;
});
});
There is some convoluted logic in the source to tell the node whether or not it needs to expand or be expandable. Take a look at the code below that I ended up resorting to when I tried to manipulate the tree programmatically:
if (!parentNode.isExpanded() && !parentNode.isLeaf()) {
parentNode.expand(false, function () {// deal with open or closed paths
console.log('expanded parent to pick up new item');
});
} else {
parentNode.callStore('suspendAutoSync');
if (parentNode.isLeaf()) { // Parts that are leafs
parentNode.set("leaf", false); //must be set to work properly
parentNode.appendChild(newPart);
parentNode.expand(); //expand to show newly created child
} else {
parentNode.insertChild(0, newPart);
}
parentNode.callStore('resumeAutoSync');
}