Does anybody know how to load data in ExtJS TreeGrid on demand? - extjs

I have found a good TreeGrid control in ExtJS library. But there is one thing, I have very big tree and I need the loading on demand.
Does anybody know how to load data in ExtJS TreeGrid on demand?
My code is here:
Ext.onReady(function () {
Ext.QuickTips.init();
var tree = new Ext.ux.tree.TreeGrid({
title: 'Encyclopedia',
width: 400,
height: 500,
animate: true,
autoScroll: true,
renderTo: "EncyclopediaTree",
containerScroll: false,
border: false,
enableDD: false,
root : new Ext.tree.AsyncTreeNode({text: 'Root'}),
loader: new Ext.tree.TreeLoader({ dataUrl: '/AdminEx/GetEncyclopediaTree' }),
columns: [{
header: 'Item',
dataIndex: 'item',
width: 230
}, {
header: 'Type',
width: 150,
dataIndex: 'type'
}]
});
});

What do you mean by on demand loading? I can see you are using asynchronous nodes, so that will be automatically on demand loaded whenever a node is expanded.

I see that you are you are using the Ext.tree.AsynctreeNode and Ext.tree.TreeLoader but the TreeGrid also has ux classes for TreeGridLoader and TreeGridNodeUI, etc.
Look at this example with Firebug's Net tab and you will see all the related files to use the TreeGrid http://dev.sencha.com/deploy/dev/examples/treegrid/treegrid.html

The example from Sencha work fine and loads data on demand as you want.
The question is whether or not it needs to load new data.
So in that example, it doesn't need to, cause no matter what parameters you pass to the dataUrl it will always return the full tree loaded.
But if there is a node in the tree without children and you don't explicitly say it's a leaf, when you expand that node it will make a new call to the dataUrl with the node id parameter.
You are responsible to return the right data from your backend, both in the initial load of all the parent nodes and everytime a new node is expanded.
You can check that it's working simply removing all children from any node, you will see that when that node is expanded it will execute an Ajax request for the new nodes (I think default method is POST).
A simple example setting request method and baseParams to be passed in the request along with the node id:
var tree = new Ext.ux.tree.TreeGrid({
renderTo: "outputDiv",
loader: new Ext.ux.tree.TreeGridLoader({
dataUrl: "general-data",
requestMethod: "GET",
baseParams: {
fromDate: "2010-01-01",
toDate: "2010-01-01",
dateField: "systemDate"
}
}),
columns:[{
header: "Customer",
dataIndex: "customer"
},{
header: "Order",
dataIndex: "orderNumber"
},{
header: "Order Line",
dataIndex: "orderLine"
},{
header: "Item",
dataIndex: "itemNumber"
}]
});
You can also add node attributes as params like this:
tree.getLoader.on("beforeload", function(treeLoader, node) {
this.baseParams.customer = node.attributes.customer;
}, this);

Just in case someone runs into this via google (like I did), the way to solve this is to do the following:
If your data has a children field, then it will not asynchronously load children.
If you want asynchronous loading, you need to remove the 'children' field from your data.
ie: This will asynchronously load when you click on the folder
[{
"ShopTree": {
"id": "ShopCategory1",
"name": "Large Items"
},
"leaf": false
}, {
"ShopTree": {
"id": "ShopCategory5",
"name": "Accessories"
},
"leaf": false
}]
while this will not asynchronously load:
[{
"ShopTree": {
"id": "ShopCategory1",
"name": "Large Items"
},
"children": [],
"leaf": false
}, {
"ShopTree": {
"id": "ShopCategory5",
"name": "Accessories"
},
"children": [],
"leaf": false
}]

Related

angularjs kendo datasource data length zero

I'm trying to get my grid (created by angular directive) populated with data, but it is not populating.
Here's my grid declaration:
<div id="dayTypesGrid" kendo-grid k-options='dayTypesGridOptions'></div>
Here's code from my angular controller:
$scope.dayTypesGridOptions = {
schema: {
model: {
id: "description",
fields: {
description: { editable: false, nullable: false },
numberOfDays: { type: "number", validation: { required: true, min: 0} }
}
}
},
columns: [{
field: "description",
title: "Day Type"
}, {
field: "numberOfDays",
title: "Number of Days"
}]
};
So far so good. The grid is instantiated, and I see the two columns. And my angular controller executes my data fetch call, and I store the result in an array $scope.viewModel.dayTypes.
Using the browser dev tools, I can see that $scope.viewModel.dayTypes indeed contains the array of 7 records.
I now want to display those 7 records in the grid, and I do so as follows:
var ds = new kendo.data.DataSource({data: $scope.viewModel.dayTypes});
$('#dayTypesGrid').data('kendoGrid').dataSource = ds;
After that last line of code, my grid still remains empty. Using the browser dev tools, I see that ds.data.length is zero.
What am I missing?
What you're looking for is the setDataSource method:
$('#dayTypesGrid').data('kendoGrid').setDataSource(ds);
Here is how I do it in my project and this works for me. Your mileage may vary because you're using data instead of a transport URL, but I noticed the structure of your grid configuration is a bit different than mine. For example, I define the schema when I create my datasource:
var datasource = new kendo.data.DataSource({
transport: {
read: {
url: "url/to/my/service",
dataType: "json"
}
},
schema: {
data: "results"
}
};
var gridConfig: {
dataSource: dataSource,
rowTemplate: $templateCache.get("modules/reports/row.html"),
height: 500,
scrollable: true,
groupable: true,
filterable: true,
pageable: true,
reorderable: true,
sortable: true,
resizable: true,
"columns": [
{
"field": "status",
"title": "Status",
"width": 200
},
{
"field": "actions",
"title": "Actions",
"width": 200
}
]
}
};

Remove and Add Gridpanel again fail with CheckboxModel in extjs4.1 and 4.2

I have a panel with layout: border, that look like http://jsfiddle.net/rpcbX/
When i click add button on west region I with removeAll from center region and add something again, in this example i add and remove gridpanel.
But My gridpanel has CheckboxModel. And that can't remove after i add gridpanel again.
Follow bellow step u will see bug.
1. Run my app and click add button
2. Click checkall butoon on gridpanel
3. Click add button again
Now u will see the bug, the selection was selected and u can't click checkall button to working. Look like
I think when i click add button then center region will has a new gridpanel (new state)
How to fix that thank
p/s: i was test that on extjs4.2.1 and the result's worse. i can't click checkbox on row ( i think i was click that but graphic not change)
Here is my code i using with add button
text: 'add',
handler: function() {
panel.down('panel[region="center"]').removeAll();
var grid = new Example();
panel.down('panel[region="center"]').add(grid);
}
You example doesn't work because you are adding instances to the prototype and those instances of store, selModel potentially columns will be shared across all the instances of Example. Your example is hitting undefined behavior. Non primitives on the prototype is generally a bad thing and for some reason I see them on stackoverflow a lot. Here is a more in depth explanation.
Doing this for Example should help fix your problem.
Ext.define('Example', {
extend: 'Ext.grid.Panel',
title: 'Simpsons',
initComponent: function() {
Ext.apply(this, {
selModel: Ext.create('Ext.selection.CheckboxModel', {
checkOnly: true,
mode: 'MULTI'
}),
store: Ext.create('Ext.data.Store', {
fields: ['name', 'email', 'phone'],
data: {
'items': [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
"email": "home#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
}),
columns: [{
header: 'Name',
dataIndex: 'name',
editor: {
xtype: 'textfield'
}
}, {
header: 'Email',
dataIndex: 'email',
flex: 1
}, {
header: 'Phone',
dataIndex: 'phone'
}
]
});
this.callParent();
}
});

ExtJs: Ext.grid.Panel: Grid refreshes automatically and becomes blank

I am using a Grid to display data on a modal window.
It has two columns, 1. Label 2. TextField
The problem I am facing is whenever I enter anything in the textfield and lose focus from that textfield (by pressing TAB or clicking somewhere else), the grid clears itself completely and I get a blank grid!
I know this has something to do with the autoSync property of the Store associated with the grid.
So I set it to false autoSync: false.
After doing this the data gets retained and works fine.
BUT when I close this modal window and re-open it with the same store data, I get a blank screen!
Following is my code:
Model
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'attribute',
type: 'string'
},
{ name: 'attributeValue',
type: 'string'
}
]
});
Store
var attrValueStore = Ext.create('Ext.data.ArrayStore', {
autoSync: true, //tried setting it to false but got error as mentioned above
model: 'Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel'
});
GRID
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueGrid', {
autoRender: true,
extend: 'Ext.grid.Panel',
alias: ['widget.attributevaluegrid'],
id: 'SQLAttributeValueGrid',
store: attrValueStore,
columnLines: true,
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})],
columns: [
{ /*Expression */
xtype: 'gridcolumn',
text: 'Attribute',
sortable: false,
menuDisabled: true,
flex: 0.225,
dataIndex: 'attribute'
},
{ /*Attribute Values*/
xtype: 'gridcolumn',
editor: 'textfield',
text: 'Values',
flex: 0.225,
dataIndex: 'attributeValue'
}
],
initComponent: function () {
this.callParent(arguments);
}
});
MODAL WINDOW
var attributeValueForm = Ext.create('Ext.window.Window', {
title:'Missing Attribute Values',
id: 'attributeValueForm',
height:500,
width:400,
modal:true,
renderTo: Ext.getBody(),
closeAction: 'hide',
items:[
{
xtype: 'attributevaluegrid',
border: false,
//height: 80,
region: 'center',
split: true
}
],
buttons: [
{
id: 'OKBtn',
itemId: 'OKBtn',
text: 'OK',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
},
{
text: 'Cancel',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
}
]
});
Please help. This is making me go mad!!
It would be helpful if you could provide details on how you create the Window itself, as it may be part of the problem.
One cause of this can be that you are hiding the window instead of closing it and then creating a new instance when you re-open. This will cause your DOM to have two windows instances and may not sync the data correctly in the second instance.
Some more details on how you create the actual window would help shed some light on whether this is the case.
I would probably want to jail myself after writing this.
The real issue was that I had created a similar grid for a different modal window and since I had copied the code I missed out on changing the ID of the new grid.
Both grids had the same IDs.
Changed it now and it is working fine now.
Thanks for your help!

UnCaught SyntaxError with extjs 4

I have been getting UnCaught SyntaxError : Unexpected Token : .
I'm really puzzled where this would come from. When i use the sample json it works
http://www.sencha.com/forum/topics-browse-remote.php
The issue maybe that i should use httpProxy. But i'm unsure how to incorporate this.
Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux', '../ux/');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.toolbar.Paging',
'Ext.ux.PreviewPlugin',
'Ext.ModelManager',
'Ext.tip.QuickTipManager'
]);
Ext.onReady(function () {
Ext.tip.QuickTipManager.init();
Ext.define('ForumThread', {
extend: 'Ext.data.Model',
fields: [
'title', 'threadid'
],
idProperty: 'threadid'
});
// create the Data Store
var store = Ext.create('Ext.data.Store', {
pageSize: 50,
model: 'ForumThread',
remoteSort: true,
proxy: {
type: 'jsonp',
//url: 'http://www.sencha.com/forum/topics-browse-remote.php',
url: 'https://www.estore.localhost/usergrid/indexgrid',
reader: {
root: 'topics',
totalProperty: 'totalCount'
},
// sends single sort as multi parameter
simpleSortMode: true
},
sorters: [{
property: 'title',
direction: 'DESC'
}]
});
// pluggable renders
function renderTopic(value, p, record) {
return "test";
}
var pluginExpanded = true;
var grid = Ext.create('Ext.grid.Panel', {
width: 700,
height: 500,
title: 'ExtJS.com - Browse Forums',
store: store,
disableSelection: true,
loadMask: true,
viewConfig: {
id: 'gv',
trackOver: false,
stripeRows: false,
plugins: [{
ptype: 'preview',
bodyField: 'excerpt',
expanded: true,
pluginId: 'preview'
}]
},
// grid columns
columns: [{
// id assigned so we can apply custom css (e.g. .x-grid-cell-topic b { color:#333 })
// TODO: This poses an issue in subclasses of Grid now because Headers are now Components
// therefore the id will be registered in the ComponentManager and conflict. Need a way to
// add additional CSS classes to the rendered cells.
id: 'topic',
text: "Topic",
dataIndex: 'title',
flex: 1,
renderer: renderTopic,
sortable: false
}],
// paging bar on the bottom
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
displayMsg: 'Displaying topics {0} - {1} of {2}',
emptyMsg: "No topics to display",
items: [
'-', {
text: 'Show Preview',
pressed: pluginExpanded,
enableToggle: true,
toggleHandler: function (btn, pressed) {
var preview = Ext.getCmp('gv').getPlugin('preview');
preview.toggleExpanded(pressed);
}
}]
}),
renderTo: 'topic-grid'
});
// trigger the data store load
store.loadPage(1);
});
Here is the json
{
"totalCount": "4",
"topics": [{
"threadid": "435",
"title": "55e38867-2b1e-4fc4-8179-5907c1c80136"
}, {
"threadid": "444",
"title": "4975db6c-d9cd-4628-a6e9-ca1d4815d28d"
}, {
"threadid": "529",
"title": "c778e5ea-eb79-42b1-8f13-7cba4600491f"
}, {
"threadid": "530",
"title": "a1024264-9eed-4784-ab91-cf2169151478"
}]
}
jsonP is a special technique for retrieving data from a server in a different domain. The main idea of jsonP is that
JsonPProxy injects a <script> tag into the DOM whenever an AJAX
request would usually be made
So imagine what would happen if proxy processed your json. It would inject <script> tag like this:
<sript>
{
"totalCount": "4",
"topics": [{
"threadid": "435",
"title": "55e38867-2b1e-4fc4-8179-5907c1c80136"
},
// ...
]
}
</script>
When this script is being executed it defenetly throws an exception.
So, like Xupypr MV has already written, you should wrap your outcoming-from-server string into:
myCallback(
//your json here
);
in this case JsonPProxy would inject <script> like this:
<sript>
myCallback({
"totalCount": "4",
"topics": [{
"threadid": "435",
"title": "55e38867-2b1e-4fc4-8179-5907c1c80136"
},
// ...
]
});
</script>
and it would be valid <script> tag.
Now you have to indicate in the store that you are using 'myCallback' as callback function (notice the callbackKey config):
var store = Ext.create('Ext.data.Store', {
// ...
proxy: {
type: 'jsonp',
url: 'https://www.estore.localhost/usergrid/indexgrid',
callbackKey: 'myCallback',
// ...
},
// ...
});
Check out docs for more info.
Notice, original (sencha example) url returns some extra data, not only json.
Make you response look like this:
Ext.data.JsonP.callback1({
"totalCount": "4",
"topics": [{
"threadid": "435",
"title": "55e38867-2b1e-4fc4-8179-5907c1c80136"
}, {
"threadid": "444",
"title": "4975db6c-d9cd-4628-a6e9-ca1d4815d28d"
}, {
"threadid": "529",
"title": "c778e5ea-eb79-42b1-8f13-7cba4600491f"
}, {
"threadid": "530",
"title": "a1024264-9eed-4784-ab91-cf2169151478"
}]
});
I was having the same problem and took me a while to figure it out.
I'm using Sencha Touch 2, which also implements the Ext.data.proxy.JsonP. The Extjs 4 proxy automatically creates a callback parameter each time it is sent to the server, e.g. callback1, callback2, sequentially. It is important to catch this parameter and return it with the json, otherwise the second time it is called it will complain not having a callback1 method.
The section "Implement on the server side" on this page
http://docs.sencha.com/touch/2-0/#!/api/Ext.data.proxy.JsonP
describes how to create callback with the JsonP. I suppose the original example http://www.sencha.com/forum/topics-browse-remote.php also does this.
I was also having the same problem, and was a mistake in server side code. I was using php file but not appended the callback going from frontend. So http://docs.sencha.com/touch/2-0/#!/api/Ext.data.proxy.JsonP is helpful which explains the structure of different types of serverside code for jsonp request
Thanks
Tapaswini

how to build tree in EXTJS?

How to build a tree in EXTJS ? It has to include the images(with '+' & '-' symbols) with respective node.Can you get me the code for the same ????
Start by defining an Ext.data.TreeStore to load your data into:
var store = Ext.create('Ext.data.TreeStore', {
proxy: {
type: 'ajax',
url: 'treeData.json'
},
root: {
text: 'Countries',
expanded: true
}
});
Json:
[{
"text": "United Kindom",
"children": [{
"text": "Glasgow",
"leaf": true
}, {
"text": "Edinburgh",
"leaf": true
}, {
"text": "London",
"leaf": true
}],
"leaf": false
},
{
"text": "France",
"leaf": true
}
...
]
Create the Tree Panel and render it to the document's body:
Ext.create('Ext.tree.Panel', {
title: 'Countries & Cities',
width: 500,
height: 300,
store: store,
useArrows: false,
rootVisible: false,
renderTo: Ext.getBody(),
style: 'margin: 50px'
});
Just look at the source code for any of the Ext JS Tree demos.
For example:
Ext.onReady(function(){
// shorthand
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: 'get-nodes.php',
root: {
nodeType: 'async',
text: 'Ext JS',
draggable: false,
id: 'src'
}
});
// render the tree
tree.render('tree-div');
tree.getRootNode().expand();
});
This looks like a good example: static tree for a static tree.
Saki makes a lot of tutorials and examples that are very helpful for EXTJS. One of Saki's Examples is an asynchronous tree. You can find it by looking to the left under state.
This seems like a good tutorial for a dynamic tree with a Ruby on Rails backend: dynamic tree with RoR backend.

Resources