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
Related
I am trying to load data in the extjs grid with paging toolbar using loaddata but it shows empty grid.
The data returned is
{
"data": [{
"id": "user1",
"title": "index0"
}, {
"id": "user2",
"title": "index1"
}, {
"id": "user3",
"title": "index2"
}, {
"id": "user4",
"title": "index3"
}],
"total": 8,
}
My code looks like
initcomponent:function(){
defaultModel:[{
header: 'Date',
dataIndex: 'id',
sortable: true
},
{
header: 'title',
dataIndex: 'title',
sortable: false,
}];
}
this.currStore = Ext.create('Ext.data.Store', {
fields : ['id','title'],
pageSize:4,
autoLoad:false,
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'data',
totalProperty:'total',
}
}
});
this.currStore.load({
params:{
start:0,
limit: 4,
}
});
var config =
{
columns : this.defaultModel,
store : this.currStore,
columnLines : true,
loadMask : true,
autoScroll : true,
tbar : [{
xtype : 'button',
text : 'Refresh',
iconCls : 'btn-refresh',
scope : this,
handler : this.refreshGridData
}],
dockedItems: [{
xtype: 'pagingtoolbar',
store: this.currStore, // same store GridPanel is using
dock: 'bottom',
id:'pagingErrNot1',
pageSize:4,
displayInfo: true,
emptyMsg: "No notification to display",
listeners:{
beforechange : {
scope : this,
fn : function(pagingtoolbar,pageNumber,scope)
{
}
}
}
}],
};
Ext.apply(this,config);
this.callParent(arguments);
}
data is of the form given above and setdata is called after the data is returned from server side.
setData:function(data)
{
this.getStore().loadData(data);
this.getView().refresh();
}
but after loadData, grid is empty and and pagingtoolbar shows disabled.WHat am i doing wrong?
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
}
]
}
};
With below configuration i am not able to populated json data in tree panel.
After loading store from server i am not able to see any records in console logs.
Is there any specific json structure need to be send from server?
Is there any configuration miss?
Below is the config i am using
MODEL
Ext.define('nsoapp.model.nso.Client', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field'
],
fields: [
{
name: 'jsxid'
},
{
name: 'name'
},
{
name: 'type'
},
{
name: 'countryId'
},
{
name: 'contact'
},
{
name: 'email'
}
]
});
STORE
Ext.define('nsoapp.store.nso.Client', {
extend: 'Ext.data.TreeStore',
requires: [
'nsoapp.model.nso.Client',
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
model: 'nsoapp.model.nso.Client',
storeId: 'nso.Client',
defaultRootProperty: 'record',
proxy: {
type: 'ajax',
url: '/client/',
reader: {
type: 'json',
root: 'populateClientRes'
}
}
}, cfg)]);
}
});
TREE PANEL
xtype: 'treepanel',
flex: 1,
margins: '0 0 3 0',
itemId: 'treeClient',
overlapHeader: false,
title: 'Clients',
titleCollapse: false,
animate: true,
displayField: 'name',
rootVisible: false,
viewConfig: {
rootVisible: false
}
In controller i am binding tree store to tree panel
var storeClient=this.getStore('nso.ordermanagement.clientcustomization.Client');
storeClient.load({
callback: function(records, operation, success) {
var treeClient=Ext.ComponentQuery.query("#treeClient")[0];
treeClient.bindStore(storeClient);
}
});
JSON DATA
{
"populateClientRes":{
"record":[
{
"name":"A_KPI",
"type":"CLIENT",
"jsxid":"14487361",
"countryId":"484",
"contact":"34434334",
"email":"",
"record":[
{
"name":"Products",
"value":"1",
"type":"PRODUCT"
},
{
"name":"Stores",
"value":"1",
"type":"STORE"
}
]
},
{
"name":"aCCStudyTest",
"type":"CLIENT",
"jsxid":"14425073",
"countryId":"484",
"contact":"1234567890",
"email":"",
"record":[
{
"name":"Products",
"value":"1",
"type":"PRODUCT"
},
{
"name":"Stores",
"value":"1",
"type":"STORE"
}
]
}
]
}
}
Short answer: JSON response is wrong!
Long answer
You specify as root populateClientRes so all children (and children of children) must use this tag.
Standard JSON response:
{
"success": true,
"children": [
{
"id": 1,
"name": "Phil",
"leaf": true
},
{
"id": 2,
"name": "Nico",
"expanded": true,
"children": [
{
"id": 3,
"name": "Mitchell",
"leaf": true
}
]},
{
"id": 4,
"name": "Sue",
"loaded": true
}
]
}
In your case you have to replace record with populateClientRes:
{
"success": true,
"populateClientRes": [
{
"name":"A_KPI",
"type":"CLIENT",
"jsxid":"14487361",
"countryId":"484",
"contact":"34434334",
"email":"",
"populateClientRes": [
{
...
}, {
...
populateClientRes: [{...},{...}]
},
]
},
{
...
}
]
}
Important notes
For all non-leaf nodes that do not have children (for example, Person with name Sue above), the server response MUST set the loaded property to true. Otherwise the proxy will attempt to load children for these nodes when they are expanded.
You find more information's here
I have a dataview that gets loaded with a parameter. I render this data in a template. I am trying to use the same data in which there is a nested item to render to a grid.
The data looks like this:
{
"myJson": {
"name": "abc",
"type": "faulty",
"notes": [
{
"date": "01-01-1970",
"note": "test note"
},
{
"date": "01-02-1970",
"note": "test note 2"
}
]
}
}
The store:
proxy: {
type: 'ajax',
url: '/api/detail/',
reader: {
type: 'json',
root: 'myJson'
}
}
Model:
{
name:'name',
},
{
name:'type',
},
{
name:'notes',
mapping:'notes'
},
Template:
{name} - {type}
That all works. What I'd like to do is use the notes chunk to display in a grid. Problem is I can't get it to read the notes group.
var notesListView = new Ext.list.ListView({
store: 'myStore',
multiSelect: false,
width:'100%',
id:'notesList',
columns: [{
header: 'Date',
width: 75,
dataIndex: 'date'
},{
header: 'Note',
width: 150,
dataIndex: 'note',
}]
});
Is it even possible to do this? Or do I need to create a new store and model to use this group of data in a grid?
I've tried mapping to notes.date, for instance, in both the model
name:'note_date',
mapping:'notes.date'
and in the grid itself
dataIndex:'notes.date'
neither of which worked.
I've also tried using renderer but this doesn't work either as it's an array
renderer:function(value, metaData, record, rowIndex, colIndex, store){
var value = value.date;//won't work; it needs an index a la value[0].date
return value;
}
You could create a nested model with the same data you are receiving. It would be like this
Ext.define("JsonModel", {
extend: 'Ext.data.Model',
fields: ['name','type'],
hasMany: [{
model: 'Note',
name: 'notes'
}]
});
Ext.define("Note", {
extend: 'Ext.data.Model',
fields: [
'date',
'note']
});
This way you could access the children of any give record like this
var jsonRecordChildren = jsronRecord.notes()
The variable jsonRecordChildren that I just created is of the type Store, so you could easily assign it to the attribute store of a grid.
Ext.create('Ext.grid.Panel', {
store: selectedRecord.notes(),
columns: [
{ text: 'Date', dataIndex: 'date' },
{ text: 'Note', dataIndex: 'note'}
],
renderTo: Ext.getBody()
});
http://jsfiddle.net/alexrom7/rF8mt/2/
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
}]