My question is similar to http://www.sencha.com/forum/showthread.php?2916-insert-update-delete-child-nodes-dynamically
only difference being that I am using Ext.Tree. I split main page into two portions.
I kept left portion for displaying data in tree structure and right portion for some displaying some details in the screen.
Currently there are some child nodes are under root node (Source). When one of child clicked, I populate some data in the right portion of screen.
Can anyone explain me to how update (insert/update/delete) child nodes dynamically when i add or delete data on right part of screen which is a grid.
Ext.onReady(function() {
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
useArrows: true,
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
border: false,
// auto create TreeLoader
dataUrl:'[JS Array]',
root: {
nodeType: 'async',
text: 'ALL',
draggable: false,
id: ''
}
});
// render the tree
tree.render('tree-div');
tree.getRootNode().expand();
});
You should look at the TreeNode class. It has methods addChild() and getPath() and removeChild that can be used to remove nodes and leaves from your treee.
EDIT: The original answer is for a deprecated version
Current Documentation Link: http://docs.sencha.com/extjs/6.2.1/classic/Ext.data.TreeStore.html#methods
Current "classic" ext appears to have unified the datasources to use something closer to a traditional data store called a TreeStore which should allow you to manipulate the tree's leaves and branches.
Related
I have a simple nesded list like
var treestore = Ext.create("Ext.NestedList", {
fullscreen: true,
updateTitleText: false,
useTitleAsBackText: false,
defaultBackButtonText: null,}
The problem is when i tap on an item it changes its own style only after a second holding, though there is need to pass that immediately
Any help will be perfect). thanks
The answer is very simple
i just had to write active atribute for the class displaing items ie :
.nav-element:active{
background:red;
}
This is my code -
var myTree = {
containerScroll: "true",
width: 500,
root: new Ext.tree.AsyncTreeNode({
id: "source",
text: "Root",
expanded: true,
draggable: true,
expandable: true
}),
loader: new Ext.tree.TreeLoader({
dataUrl: 'page.php?action=Get_Tree',
preloadChildren: true,
expandAll: function () {}
}),
xtype: "treepanel",
loadMask: {
msg: 'Loading...'
},
maskDisabled: false,
id: "tree",
listeners: {
click: function (node, event) {
// Render entity data in right panel
handleAction(node);
}
}
}
when user clicks on any node of Tree, I fetch the data from DB and rendering the another panel using handleAction method. In my case, I need to show node's info in another panel and update it. On update handler, I need to change node's text/id as its updated now.
This works fine but then I need to refresh the tree so that, I can view updated node. But, it doesn't work for me :(.
This is my code for updating node -
var tree = Ext.getCmp('tree');
var id = req.responseText.split('#')[1];
var myId = 'Spec#' + entityId;
var node = tree.getNodeById(myId);
node.id = 'Spec#' + id;
node.text = updated_spec_id;
tree.enable();
tree.getLoader().dataUrl = 'page.php?todo=Get_Tree';
tree.getLoader().load(tree.root);
// This I have tried but not succeed.
tree.getView().refresh();
tree.expandAll();
node.expand();
tree.getRootNode().expand(true);
However, when I manually expand it using mouse click, node is updated.
Please help. Thanks in advance.
Have you tried doLayout function? Excerpt from doc:
If the Container is already rendered when add is called, you may need to call doLayout to refresh the view which causes any unrendered child Components to be rendered. This is required so that you can add multiple child components if needed while only refreshing the layout once.
It seems to me, your tree doing normal behaviour. Because, you had used click event, therefore this event fire when you click the node.
I have a treepanel listing a complex hierachy of nodes.
If the list of nodes gets too big then the panel scrolls which is desired.
What is not desired is the ability of a user to click the arrow (or dblclick the item) to expand/collapse parent nodes.
What is the simplest way to ensure a treepanel always renders fully expanded and the expand/collapse functionality is removed?
I once needed to do this, and this solution(found here) worked for me:
For each uncollapsible node:
{text: 'Node', nodeType: 'node', expanded: true, cls: 'uncollapsible', collapsible: false}
In your CSS:
.uncollapsible .x-tree-elbow-minus {
background-image: url(resources/images/default/tree/elbow.gif);
}
.uncollapsible .x-tree-elbow-end-minus {
background-image: url(resources/images/default/tree/elbow-end.gif)
}
in your TreePanel:
listeners: {
beforecollapsenode: function(node) {
return node.attributes.collapsible;
}
}
I've created a panel bundled with an Ext.Template. This panel is contained in another panel that starts its life collapsed.
id: 'myPanel',
title: 'My Title',
layout: 'border',
collapsible: true,
collapsed: true,
hideCollapseTool:true,
bodyBorder: false,
height: 300,
bodyStyle: 'background:#F9F9F9;',
items: [{
id: 'myDisplayPanel',
bodyStyle: 'background:transparent;',
width: 300,
border: false,
margins: '5 5 5 5',
region: 'west',
tpl: new Ext.Template([
'some template'
])
},
{
id: 'myForm',
xtype: 'form',
bodyStyle: 'background:transparent;',
border: false,
margins: '5 5 5 5',
region: 'center',
[...]
This template-panel is supposed to be updated as the result of a row select in a neighbouring grid. But I get an error the first time I call .update(data); on the myDisplayPanel, as it contains no body element.
myGridSelectionModel: new Ext.grid.RowSelectionModel({
singleselect: true,
listeners: {
rowselect: function(sm,rowIdx,r) {
Ext.getCmp('myDisplayPanel').update(r.data);
Ext.getCmp('myPanel').expand(true);
}
}
}),
The call to myDisplayPanel.update() causes an error when Ext tries to call the template.overwrite function with myDisplayPanel.body as the first param.
function(b,a,c){b=Ext.getDom(b);b.innerHTML=this.applyTemplate(a);
Is it possible somehow to force Ext to generate a body element for this hidden panel before it is beeing shown? I've tried to expand the element prior to updating it, but this has now effect...
I know this thread is 2 months old, so I'm not sure if you ever found a solution. However, I just ran into the same thing and came across your thread while looking for an answer. This is what I ended up doing:
Where you're currently running panel.update(content), try this:
if(panel.rendered) panel.update(content);
else panel.contentToLoad = content;
Set up a listener for the render event to run:
if(this.contentToLoad) panel.update(this.contentToLoad);
That way, if the panel isn't rendered, it will store the content somewhere and the render listener will load whatever is there when the panel IS rendered.
Collapsed panels (and hidden containers in general) by default do not layout their children until they first become visible. You can override this behavior by setting forceLayout: true on the collapsed container. As the name suggests, this will force the container to perform its layout whether it is visible or not. Note that in your case this would be myPanel that would need this configuration, not myDisplayPanel.
You might try Panel's elements config, which from the docs is "A comma-delimited list of panel elements to initialize when the panel is rendered." So e.g.,
elements: ['header','body']
However it already defaults to 'body' only, so it may just be that the panel is truly not rendered yet when you are updating it. Try reversing the order of your calls so that the container is expanded first (should force the child panel to render) then update it.
I'm trying to create a dynamic grid using ExtJS. The grid is built and displayed when a click event is fired then an ajax request is sent to the server to fetch the columns, records and records definition a.k.a store fields.
Each node could have different grid structure and that depends on the level of the node in the tree.
The only way I came up with so far is :
function showGrid(response, request) {
var jsonData = Ext.util.JSON.decode(response.responseText);
var grid = Ext.getCmp('contentGrid' + request.params.owner);
if (grid) {
grid.destroy();
}
var store = new Ext.data.ArrayStore({
id: 'arrayStore',
fields: jsonData.recordFields,
autoDestroy: true
});
grid = new Ext.grid.GridPanel({
defaults: {
sortable: true
},
id: 'contentGrid' + request.params.owner,
store: store,
columns: jsonData.columns,
//width:540,
//height:200,
loadMask: true
});
store.loadData(jsonData.records);
if (Ext.getCmp('tab-' + request.params.owner)) {
Ext.getCmp('tab-' + request.params.owner).show();
} else {
grid.render('grid-div');
Ext.getCmp('card-tabs-panel').add({
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
html: Ext.getDom('grid-div').innerHTML,
closable: true
}).show();
}
}
The function above is called when a click event is fired
'click': function(node) {
Ext.Ajax.request({
url: 'showCtn',
success: function(response, request) {
alert('Success');
showGrid(response, request);
},
failure: function(results, request) {
alert('Error');
},
params: Ext.urlDecode(node.attributes.options);
}
});
}
The problem I'm getting with this code is that a new grid is displayed each time the showGrid function is called. The end user sees the old grids and the new one. To mitigate this problem, I tried destroying the grid and also removing the grid element on each request, and that seems to solve the problem only that records never get displayed this time.
if (grid) {
grid.destroy(true);
}
The behaviour I'm looking for is to display the result of a grid within a tab and if that tab exists replaced the old grid.
Any help is appreciated.
When you are trying to add your grid to the tab like this:
html:Ext.getDom('grid-div').innerHTML,
Ext is not aware of it being a valid grid component. Instead, you are simply adding HTML markup that just happens to look like a grid, but the TabPanel will not be aware that it is a grid component.
Instead you should add the grid itself as the tab (a GridPanel is a Panel and does not need to be nested into a parent panel). You can do so and also apply the needed tab configs like this:
Ext.getCmp('card-tabs-panel').add({
Ext.apply(grid, {
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
closable: true
});
}).show();
BTW, constantly creating and destroying grids is not an ideal strategy if you can avoid it. It might be better to simply hide and re-show grids (and reload their data) based on which type of grid is needed if that's possible (assuming the set of grid types is finite).
A potential option is to use the metaData field on the JsonStore that allows dynamic reconfiguring of the grid columns as per new datasets.
From
One of the most helpful blog posts about this that Ive found is this one:
http://blog.nextlogic.net/2009/04/dynamic-columns-in-ext-js-grid.html and the original info is well documented at http://docs.sencha.com/ext-js/3-4/#!/api/Ext.data.JsonReader