(i posted this on the extjs forum too but recon SO is probably busier)
HI
I'm passing down the following json to a direct store:
{
"type": "rpc",
"tid": 2,
"action": "DirectReportDesigner",
"method": "GetReports",
"result": {
"total": 1,
"data": [{
"id": 1,
"FullTypeName": null,
"title": "test",
"useGroupedColConfig": false,
"groupTextTemplate": "{'ProviderName': ' Contract Number -- {gvalue}','ProviderName': ' Provider Name -- {gvalue}'}",
"groupHeaders": null,
"groupFields": "['CostElement2', 'CostElement3', 'CostElement4']",
"groupedHeaders": false,
"jsonUrl": "report/BudgetManagerBudgetData.rails",
"menuType": "rptmid",
"actualType": "rptmid",
"ignoreCols": "1",
"getRowClass": "settings.utils.highlightRowWhenCellEmptyClass",
"deleted": false,
"fitToScreen": false,
"isCopyOf": 0
}]
}
}
here is what the js code looks like:
Ext.extend(Ideal.ReportDesigner.ReportGrid, Ideal.UI.BaseGrid, {
pageSize: 25,
afterRender: function() {
this.getStore().load({
params: {
start: 0,
limit: 25
}
});
Ideal.ReportDesigner.ReportGrid.superclass.afterRender.apply(this, arguments);
},
header: false,
view: new Ext.grid.GridView({
autoFill: true
}),
cm: new Ideal.UI.ColumnModel([{
header: 'Report Name',
id: 'nameCol',
sortable: true,
dataIndex: 'title'
}, {
header: 'Json URL',
sortable: true,
dataIndex: 'jsonUrl'
}, {
header: 'Group Text Template',
sortable: true,
dataIndex: 'groupTextTemplate'
}, {
header: 'Group Headers',
sortable: true,
dataIndex: 'groupHeaders'
}, {
header: 'Group Fields',
id: 'groupFieldsCol',
sortable: true,
dataIndex: 'groupFields'
}, {
header: 'Grouped Headers',
sortable: true,
dataIndex: 'groupedHeaders'
}, {
header: 'Fit to Screen',
sortable: true,
dataIndex: 'fitToScreen'
}, {
header: 'Ignore Cols',
sortable: true,
dataIndex: 'ignoreCols'
}, {
header: 'Get Row Class',
sortable: true,
dataIndex: 'getRowClass'
}
]),
initComponent: function() {
var ds = new Ext.data.DirectStore({
directFn: DirectReportDesigner.GetReports,
paramsAsHash: false,
paramOrder: 'start|limit|sort|dir',
root: 'data',
idProperty: 'id',
totalProperty: 'total',
sortInfo: {
field: 'title',
direction: 'ASC'
},
fields: [{
name: 'id'
}, {
name: 'title'
}, {
name: 'useGroupedColConfig'
}, {
name: 'groupTextTemplate'
}, {
name: 'groupHeaders'
}, {
name: 'groupFields'
}, {
name: 'groupedHeaders'
}, {
name: 'jsonUrl'
}, {
name: 'menuType'
}, {
name: 'actualType'
}, {
name: 'fitToScreen'
}, {
name: 'ignoreCols'
}, {
name: 'getRowClass'
}, {
name: 'isCopyOf'
}
],
remoteSort: true
});
var pager = new Ext.PagingToolbar({
store: ds,
displayInfo: true,
pageSize: this.pageSize
});
var config = {
store: ds,
bbar: pager
};
Ext.apply(this, Ext.apply(this.initialConfig, config));
Ideal.ReportDesigner.ReportGrid.superclass.initComponent.apply(this, arguments);
}
});
the grid renders ok, the server code to get the json fires ok, but the store never loads the data. i know it's being passed back as i can see it in firebug and that's how i pasted it above.
can anyone see anything obvious here?
cheers
w://
I've always defined store's fields as an array of strings, not as objects.
fields: ['id','title','useGroupedColConfig', ...]
i managed to sort this - it was the name of the c# variable that was getting serialized that was throwing it - why i have no idea!!!
Related
I'm trying to put a GridPanel powered by an ArrayStore in a Window, but no matter what I do, it just looks like this with no data rows inside:
Here's my code:
var ticketsStore = new Ext.data.ArrayStore
(
{
autoDestroy: false,
remoteSort: false,
data: result,
fields:
[
{ name: 'articleId', type: 'int' },
{ name: 'heatTicketRef', type: 'string' },
{ name: 'username', type: 'string' },
{ name: 'dateLinked', type: 'date' }
]
}
);
var ticketsGrid = new Ext.grid.GridPanel({
store: ticketsStore,
id: this.id + 'ticketsGrid',
viewConfig: {
emptyText: 'No data'
},
autoShow: true,
idProperty: 'heatTicketRef',
columns: [
{ id: 'heatTicketRef', header:"Ticket ID", width: 100, dataIndex: 'heatTicketRef', sortable: false },
{ header: "User", width: 100, dataIndex: 'username', sortable: false },
{ header: "Date Linked", width: 100, dataIndex: 'dateLinked', xtype: 'datecolumn', format: 'j M Y h:ia', sortable: false }
]
});
var window = new Ext.Window
(
{
renderTo: Ext.getBody(),
id: this.id + 'linkedHeatTickets',
closable: true,
modal: true,
autoHeight: true,
width: 500,
title:'Linked Heat Tickets',
resizable: false,
listeners:
{
close: function () { // do something }
},
items:
{
style: 'padding:5px;',
items: ticketsGrid
},
buttons:
{
text: 'Close',
handler: function () {
window.close();
}
}
}
);
window.show();
When I debug, I can see that my "result" object is healthy and the ArrayStore is of the right length:
But the GridPanel doesn't like the data because it's not in its items (although it's in the store) array:
What little thing have I done wrong?
Thanks!
Because I'm an idiot... I used an ArrayStore instead of a JsonStore!
I have a grid with a pagination. When I set a filter, the ajax request is successfully executed, the json return value looks fine and the filtered rows appear in my grid.
But the Loading... popup won't disappear and Firebug reports an error in ext-all-debug.js: TypeError: data is null (Line 134684). The code at that point is:
data = store.getData();
items = data.items; // error
I've checked my JS several times, but I can't find the problem.
Unfortunately I can't create a fiddle, since I use remote filtering. So here's the script:
Ext.onReady (function () {
Ext.define('FooModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'myId', type: 'int' },
{ name: 'myDate', type: 'date', dateFormat: 'Y-m-d H:i:s' },
{ name: 'myString', type: 'string' },
{ name: 'myFilename', type: 'string' },
{ name: 'myUser', type: 'string' }
]
});
Ext.define('FooStore', {
extend: 'Ext.data.Store',
model: 'FooModel',
autoLoad: true,
autoDestroy: true,
proxy: {
type: 'ajax',
url: 'test.php',
reader: {
type: 'json',
rootProperty: 'import_files',
messageProperty: 'error',
}
},
remoteFilter: true,
remoteSort: true,
sorters: [{
property: 'myId',
direction: 'ASC'
}],
pageSize: 5
});
var theFooStore = new FooStore();
theFooStore.load({
callback: function(records, operation, success) {
if(!success) {
Ext.Msg.alert('Error', operation.getError());
}
}
});
Ext.define('FooGrid', {
extend: 'Ext.grid.Panel',
xtype: 'grid-filtering',
requires: [ 'Ext.grid.filters.Filters' ],
width: 1000,
height: 700,
renderTo: 'content',
plugins: 'gridfilters',
emptyText: 'No Matching Records',
loadMask: true,
stateful: true,
store: theFooStore,
defaultListenerScope: true,
columns: [
{ dataIndex: 'myId', text: 'My Id', filter: 'number' },
{ xtype: 'datecolumn', dataIndex: 'myDate', text: 'My Date', renderer: Ext.util.Format.dateRenderer('d.m.Y'), filter: true },
{ dataIndex: 'myString', text: 'My String', filter: 'list' },
{ dataIndex: 'myFilename', text: 'My Filename',
renderer: function(value, meta, record) {
return Ext.String.format('{1}', record.data.myId, value);
},
filter: {
type: 'string',
itemDefaults: { emptyText: 'Search for...' }
}
},
{
dataIndex: 'myUser', text: 'My User',
filter: {
type: 'string',
itemDefaults: { emptyText: 'Search for...' }
}
},
],
dockedItems: [{
xtype: 'pagingtoolbar',
store: theFooStore,
dock: 'bottom',
displayInfo: true
}]
});
new FooGrid();
});
And here's a sample json return value:
{
"success" : true,
"total" : 19,
"import_files" : [{
"myId" : "1",
"myFilename" : "foo bar.xlsx",
"myDate" : "2015-05-19 13:23:21",
"myUser" : "ABC",
"myString" : "Lorem ipsum"
},
...
]
}
Has someone experienced the same issue? What could it cause?
Just my luck. Found the answer shortly after posting the question.
Deleting the filter: 'list' option at my My String column is the solution.
Model
Ext.define('XXX.User', {
extend: 'Ext.data.Model',
fields: [
'name',
'email',
'nick',
'mobile',
{ name: 'create_time', type: 'date', dateFormat: 'Y-m-d H:i:s' }
]
});
Ajax Response
{
"error": "",
"errno": 0,
"success": true,
"message": "Operation performed successfully",
"data": [{
"nick": "muquaddim1",
"name": "Muquaddim One",
"id": "141",
"mobile": "01710000***",
"email": "muquaddim+1#example.com",
"create_time": "2012-02-26 14:58:29"
}]
}
Store
var user_store = Ext.create('Ext.data.Store', {
// destroy the store if the grid is destroyed
autoDestroy: true,
autoLoad: true,
model: 'XXX.User',
sotreId: 'user-store',
proxy: {
type: 'ajax',
url : 'proxy/user'
},
sorters: [{
property: 'create_time',
direction: 'ASC'
}]
});
Grid
var user_grid = Ext.create('Ext.grid.Panel', {
title: 'List of Users',
store: user_store,
columns: [{
header: 'Nick',
dataIndex: 'nick',
editor: {
allowBlank: false
}
}, {
header: 'Name',
dataIndex: 'name',
flex: 1,
editor: {
allowBlank: false
}
}, {
header: 'Email',
dataIndex: 'email',
width: 160,
editor: {
allowBlank: false,
vtype: 'email'
}
}, {
header: 'Mobile',
dataIndex: 'mobile',
width: 100,
editor: {
allowBlank: false
}
}, {
xtype: 'datecolumn',
header: 'Join Date',
dataIndex: 'create_time',
width: 90,
editor: {
xtype: 'datefield',
allowBlank: false,
format: 'Y-m-d H:i:s',
maxValue: Ext.Date.format(new Date(), 'Y-m-d H:i:s')
}
}]
});
Panel
var users = Ext.create('Ext.panel.Panel', {
title: 'Users',
id: 'user_panel',
items:[user_grid]
});
I am using ExtJS 4.0.7. I modified the code found in Example. Example code works fine. But it does not work. What am I missing here?
Since your data is nested in your response you need to configure a reader in your store's proxy. Try setting up your proxy like this:
proxy: {
type: 'ajax',
url : 'proxy/user'
reader: {
type: 'json',
root: 'data'
}
}
I am trying to create a grid builder object. This grid builder has a method, buildGrid, which I've designed to expect an object defining a bunch of paramaters for a grid:
buildOrdersGrid: function () {
var ordersGrid = buildGrid({
gridElementID: 'OrdersGrid',
gridPagerElementID: 'OrdersGridPager',
colNames: ['Order ID', 'Project Subcode', 'Incident Number', 'Cost Center', 'Name', 'Customer'],
colModel: [
{ name: 'ID', hidden: true },
{ name: 'ProjectSubcode' },
{ name: 'IncidentNumber' },
{ name: 'CostCenter' },
{ name: 'Name' },
{ name: 'Customer' }
],
defaultCaption:'Orders: no filter applied',
});
return ordersGrid;
}
function buildGrid(data) {
var grid = $('#' + data.gridElementID);
var gridPager = $('#' + data.gridPagerElementID);
grid.jqGrid({
datatype: 'local',
colNames: data.colNames,
colModel: data.colModel,
gridview: true,
height: 'auto',
pager: gridPager,
viewrecords: true,
multiselect: true,
defaultCaption: data.defaultCaption,
caption: data.defaultCaption,
shrinkToFit: false
});
return grid;
}
Something like that, but it's really new code, so open to advice on how to improve.
Now, I would like to extend this buildGrid method such that it can take non-predefined properties and give them to the jqGrid. Something like:
buildTaskGrid: function () {
var tasksGrid = buildGrid({
gridElementID: 'TasksGrid',
gridPagerElementID: 'TasksGridPager',
colNames: ['Order', 'Task ID', 'Task #', 'Type', 'Status', 'Assignee', 'Current Location', 'Dest Location', 'Change No', 'Net Patched', 'SAN Patched'],
colModel: [
{ name: 'Order' },
{ name: 'TaskID', hidden: true },
{ name: 'TaskNo' },
{ name: 'Type' },
{ name: 'Status' },
{ name: 'Assignee' },
{ name: 'CurrentLocation' },
{ name: 'DestLocation' },
{ name: 'ChangeNo' },
{ name: 'NetPatched' },
{ name: 'SANPatched' }
],
defaultCaption:'Tasks: no filter applied',
//Decorate with task-specific properties.
grouping: true,
groupingView: {
groupField: ['Order'],
groupColumnShow: [false]
},
ondblClickRow: function (rowid) {
$(this).trigger('taskDoubleClicked', selector.getRowData(rowid));
}
});
return tasksGrid;
}
I'm not sure how I should best 'find' the unanticipated properties and give them to the grid. Any ideas?
I think you can use this http://api.jquery.com/jQuery.extend/
I would like to implement a tree panel with content loaded dynamically from the server (as Json) and with a custom data model. But I dont know how to define a model and a data store for that tree. Can you provide some examples? If possible, I'd like to conform to the sencha mvc recommendations (the model and the data store defined as separate classes).
I knew how to do it in extjs 3 but i'm lost in version 4.
Best regards
RG
I experimented with a new MVC approach recently, and I managed to get it work with the treepanel. Nothing special actually:
View:
Ext.define('RoleBuilder.view.RoleList', {
extend: 'Ext.tree.Panel',
alias: 'widget.roles',
title: 'Roles',
store: 'Roles'
});
Store:
Ext.define('RoleBuilder.store.Roles', {
extend: 'Ext.data.TreeStore',
model: 'RoleBuilder.model.Role',
requires: 'RoleBuilder.model.Role',
root: {
text: 'Roles',
expanded: true
},
proxy: {
type: 'ajax',
url: loadRolesUrl,
actionMethods: 'POST',
reader: {
type: 'json'
}
}
});
Model:
Ext.define('RoleBuilder.model.Role', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int', mapping: 'Id' },
{ name: 'text', type: 'string', mapping: 'Text' },
{ name: 'leaf', type: 'boolean', mapping: 'Leaf' },
{ name: 'loaded', type: 'boolean', mapping: 'Loaded', defaultValue: false },
{ name: 'Properties'},
{ name: 'expanded', defaultValue: true }
]
});
Controller:
Ext.define('RoleBuilder.controller.RoleList', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'roles': {
itemcontextmenu: this.onItemContextMenuClick,
itemclick: this.onItemClick
}
});
this.application.on({
'role-saved': Ext.Function.bind(this.onRoleSaved, this)
});
},
..... too long, but you got the idea.
Hope it will help.
I struggle so much to get this working. I want to share with you in case you need it.
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: "problems",
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 store:
Ext.define("GiipIq.store.Problems", {
extend: "Ext.data.TreeStore",
storeId:"problems-store",
model: "GiipIq.model.Problem",
});
Here is my model:
Ext.define("GiipIq.model.Problem", {
extend: "Ext.data.Model",
fields: [
{ name: "text", type: "string" },
{ name: "leaf", type: "bool" },
{ name: "expanded", type: "bool" },
{ name: "checked", type: "bool" }
],
proxy: {
type: "ajax",
actionMethods: { read: "GET" },
api: { read: "app/problems.json", },
reader: {
type: "json",
root: "children"
},
listeners: {
exception: function(proxy, response, operation, opts) {
if(typeof(operation.error) == "string") {
Ext.Msg.alert("Error", "Connection to server interrupted" + operation.error);
}
}
}
}
});
Here is my json:
{
success: true,
children: [{
text: "algorithms", expanded: true, leaf: false, checked: false, children: [
{ text: "bit manipulation", leaf: true, checked: true },
{ text: "brain teaser", leaf: true, checked: true }
]
},{
text: "data structures", expanded: true, checked: false, leaf: false, children: [
{ text: "array and strings", leaf: true, checked: true },
{ text: "linked lists", leaf: true, checked: false}
]
},{
text: "knowledge based", expanded: true, leaf: false, checked: false, children: [
{ text: "C and C++", leaf: true, checked: false},
{ text: "Java", leaf: true, checked: false}
]
}]
}