I use an editorgrid to edit elements from a JsonStore. The JsonStore uses a HttpProxy to update the backend database.
My problem is that the backend API expects fromTs and toTs to be Unix timestamps, but when a record is updated, the resulting http post contains a date formatted like this: Wed Oct 20 00:00:00 UTC+0200 2010
I've searched the API documentation for a parameter to control the post format, but I've not been able to find anything. Is there a simple way to do this?
myJsonStore = new Ext.data.JsonStore({
autoLoad: true,
autoSave: true,
proxy: new Ext.data.HttpProxy({
api: {
create: '/create/',
read: '/read/',
update: '/update/',
destroy:'/destroy/'
}
}),
writer: new Ext.data.JsonWriter({
encode: true,
writeAllFields: true
}),
idProperty: 'id',
fields: [
{name: 'id', type: 'int'},
{name: 'fromTs', type: 'date', dateFormat:'timestamp'},
{name: 'toTs', type: 'date', dateFormat:'timestamp'}
]
});
The editorgrid is configured like this:
{
xtype: 'editorgrid',
clicksToEdit: 1,
columns: [
{header: "Id", dataIndex: 'id', editable: false},
{header: "From", dataIndex: 'fromTs', editor: new Ext.form.DateField({format: 'd.m.Y', startDay: 1}), xtype: 'datecolumn', format: 'd.m.Y'},
{header: "To", dataIndex: 'toTs', editor: new Ext.form.DateField({format: 'd.m.Y', startDay: 1}), xtype: 'datecolumn', format: 'd.m.Y'}
],
store: myJsonStore
}
I know this case is old, but I found a solution to this problem that I never came around to post here.
I added a listener to the proxy's beforewrite event, and manipulated the post params there
proxy: new Ext.data.HttpProxy({
api: {
create: '/create/',
read: '/read/',
update: '/update/',
destroy:'/destroy/'
},
listeners: {
beforewrite: function(proxy, action, record, params) {
var fromTs = record.data.fromTs;
var toTs = record.data.toTs;
if(record.data.fromTs) record.data.fromTs = fromTs.format('U');
if(record.data.toTs) record.data.toTs = toTs.format('U');
// Update record to be sent
// root = store.reader.root
params.root = Ext.util.JSON.encode(record.data);
// Restore record
record.data.fromTs = fromTs;
record.data.toTs = toTs;
}
}
})
You might be able to hook into the validateedit event or afteredit event of your EditorGridPanel and convert the user-entered-value back into a timestamp using a Date parsing method. I'm guessing that EditorGridPanel is updating the records in the store verbatim without converting them back into timestamps, so you have to do that manually. So I'm thinking maybe something like:
grid.on('validateedit', function(event) {
if (isDateColumn(column)) {
event.record.data[event.field] = dateToTimestamp(event.value);
}
}
The problem is that the JsonWriter does not respect the dateFormat field used in your JsonReader. This post describes the issue along with some code that will address it. You can find it here.
Related
Fiddle with the problem is here https://fiddle.sencha.com/#view/editor&fiddle/2o8q
There are a lot of methods in the net about how to locally filter grid panel that have paging, but no one is working for me. I have the following grid
var grid = Ext.create('Ext.grid.GridPanel', {
store: store,
bbar: pagingToolbar,
columns: [getColumns()],
features: [{
ftype: 'filters',
local: true,
filters: [getFilters()],
}],
}
Filters here have the form (just copy pasted part of my filters object)
{
type: 'string',
dataIndex: 'name',
active: false
}, {
type: 'numeric',
dataIndex: 'id',
active: false
},
The store is the following
var store = Ext.create('Ext.data.Store', {
model: 'Store',
autoLoad: true,
proxy: {
data: myData,
enablePaging: true,
type: 'memory',
reader: {
type: 'array',
}
},
});
Here myData - comes to me in the form of
["1245", "Joen", "Devis", "user", "", "email#com", "15/6/2017"],
["9876", "Alex", "Klex", "user", "", "email#com", "15/6/2017"],[...
Also I have the the pagingToolbar
var pagingToolbar = Ext.create('Ext.PagingToolbar', {
store: store, displayInfo: true
});
So all the elements use the store I declared in the top. I have 25 elements per grid page, and around 43 elements in myData. So now I have 2 pages in my grid. When I am on first page of grid and apply string filter for name, for example, it filters first page (25 elements), when I move to 2d page, grid is also filtered, but in scope of second page. So as a result each page filters seperately. I need to filter ALL pages at the same time when I check the checkbox of filter, and to update the info of pagingToolbar accordingly. What I am doing wrong?
Almost sure that it is a late answer, but I have found the local store filter solution for paging grid you are probably looking for:
https://fiddle.sencha.com/#fiddle/2jgl
It used store proxy to load data into the grid instead of explicitly specify them in store config.
In general:
create empty store with next mandatory options
....
proxy: {
type: 'memory',
enablePaging: true,
....
},
pageSize: 10,
remoteFilter: true,
....
then load data to the store using its proxy instead of loadData
method
store.getProxy().data = myData;
store.reload()
apply filter to see result
store.filter([{ property: 'name', value: 'Bob' }]);
See President.js store configuration in provided fiddle example for more details.
Hope it helps
I currently have a simple extJS Grid which is pulling data from a server and presenting it to the viewer. I would like to grab the value of the selected row, and then pass it to another PHP script for processing in order to display the results in another grid.
var roleInformationStore = Ext.create('Ext.data.Store', {
autoLoad: true,
autoSync: true,
model: 'RoleInformation',
proxy: {
type: 'ajax',
url: 'data.php',
reader: {
type: 'array',
},
writer: {
type: 'json'
}
}
});
var roleInformationGrid = Ext.create('Ext.grid.Panel', {
store: roleInformationStore,
width: '100%',
height: 200,
title: 'Roles',
columns: [
{
text: 'Name',
flex: 1,
width: 100,
sortable: false,
hideable: false,
dataIndex: 'role'
}
],
listeners: {
cellclick: function(view, td, cellIndex, record, tr, rowIndex, e, eOpts) {
roleInformationStore.proxy.extraParams = record.get('role');
//Ext.Msg.alert('Selected Record', 'Name: ' + record.get('role'));
}
}
});
Using the listener in the current grid, I am able to get the value and show it using the alert method. Any suggestions on how to accomplish this?
Thanks
For this to work, extraParams has to be an object of key-value string pairs, because an URI has to be something like data.php?key1=value1&key2=value2.
Style-wise, Sencha advises to use getters and setters, whenever possible.
Together, you get:
var store = Ext.getStore("roleInformationStore");
store.getProxy().setExtraParam("myRoleParamKey",record.get('role'));
store.load();
In PHP, you would get the parameter then using
$role = $_GET['myRoleParamKey'];
You can of course substitute myRoleParamKey for any alphanumeric literal you want, but make sure you use the same key on both server and client side. ;-)
Docs: setExtraParam
I've created an Ext.tree.Panel view.
Ext.define('MyApp.requests.view.QueryRequestsGridView', {
extend: 'Ext.tree.Panel',
useArrows: true,
rootVisible: false,
singleExpand: true,
bind: {
store: '{queryRequestsGrid}'
},
viewConfig:{
markDirty: false
},
columns: [
{ text: 'Id', dataIndex: 'id', flex: 3},
{ xtype: 'treecolumn', text: 'Name', dataIndex: 'name', flex: 6},
{ text: 'ControlType', dataIndex: 'controlType', flex: 4, sortable: false},
{ text: 'Description', dataIndex: 'description', flex: 6}
],
dockedItems: [{
xtype: 'pagingtoolbar',
bind: {
store: '{queryRequestsGrid}'
},
displayInfo: true
}]
}]
});
As I can see from the docs the store of Ext.tree.Panel should be Ext.data.TreeStore.
Ext.define('MyApp.requests.model.QueryRequestsGridModel', {
extend: 'Ext.data.TreeModel',
fields: [
{name: 'id'},
{name: 'name'},
{name: 'controlType'},
{name: 'description'}
]
});
Ext.define('MyApp.requests.store.QueryRequestsGridStore', {
extend: 'Ext.data.TreeStore',
model: 'MyApp.requests.model.QueryRequestsGridModel',
pageSize: 10,
alias: 'store.queryRequestsGrid',
root: {
expanded: false
},
remoteSort: true,
proxy: {
startParam: 'start',
limitParam: 'limit',
pageParam: undefined,
sortParam: undefined,
noCache: false,
type: 'ajax',
url: 'ucis.json'
}
});
Now on view creation the TreeStore data is requested using the following url without start and limit params but with nodeParam instead:
ucis.json?node=root
If to replace Ext.data.TreeStore with Ext.data.Store the following url will be sent:
ucis.json?offset=0&limit=10
The question is: does a treestore support start and limit pagingtoolbar parameters?
You can easily paginate a list. But the concept of tree pagination isn't disambiguous, I fear.
When thinking of the tree like an indented list, there would evidently be pages with leaves which are neither root nor have parents that have been sent to the client (because they are not on the page you requested). But the TreeStore does not work like an indented list; it works with a root and child nodes. This is why there is no builtin pagination support for TreeStore. Furthermore, PagingToolbar can only work with a list of nodes, not with a tree.
As per Pagination in Ext Tree, TreeStore does not require a full tree; it can work with a tree that is not fully loaded, and can dynamically fetch child nodes of a certain node whenever you expand the node. This is what you are using.
When thinking of every node's child nodes as a list, there is no builtin way to split the 1000 child nodes of a node into pages automatically. You can, however, extend the TreeStore to allow for that; there is no hard technical boundary against it. But you would have to extend the TreeGrid with a BufferedRenderer as well, which is not as easy as it may sound. The biggest hurdle would be using pagingToolbar, you won't be easily able to use that or extend from it, since it binds to the grid and works with that, but you need pagination on every node's child list. Because, if your root has a list of 1000 nodes and you open one of these nodes with 500 child nodes, how would the pagingToolbar know which node's children you want to page through?
Answering to my own question:
Yes, it is possible to send start and limit parameters from viewcontroller (for example, on afterrender event) using store.load
store.load({
params: {
start: 0,
limit: store.pageSize
}
});
The TreeStore will not send those parameters itself on the first load because does not support pagination from the box.
I am new to ExtJS and I find documentation confusing, I need to get the first data from store, which I get from the report. How to do it correctly?
this.divisionList = new ....SimplestReportCombo({
fieldLabel: "Division",
allowBlank: false,
valueField: 'KEY',
displayField: store.load.get(0),
width: 200,
reportID: 'USER_ACCESS',
store : new Ext.data.ArrayStore({
fields: [{name: 'KEY'}],
data: [{name: 'VALUE'}]
}
)
});
Javascript Stores mostly resembles RDBMS tables. They have in memomy storage and they are helpful to perform various grid level operation like sorting , paging , shuffling , editing etc.
Lets come to your code now,
You dont need to load store get its elements.If you requirement is only to select 1st ellement from store then you can do that using getAt function like below:
this.divisionList = new ....SimplestReportCombo({
fieldLabel: "Division",
allowBlank: false,
valueField: 'KEY',
displayField: store.getAt(0),
width: 200,
reportID: 'USER_ACCESS',
store : new Ext.data.ArrayStore({
fields: [{name: 'KEY'}],
data: [{name: 'VALUE'}]
}
)
});
or else you can also use following store method if you want to render mere 1st element:
store.first()
I have checked the API and is supposed to exist a method from GridPanel that is addLister, so ok I try to use it:
function showCreatePatientCoincidencesWindow(matches, patientData, actuallyCreate) {
var grid = new GridPanel('idGrid', '', null, 250);
grid.addColumn(new GridColumn('idgridColumn0LC', 'Nombre', "cName"));
grid.addColumn(new GridColumn('idgridColumn1LC',' Apellido1', "cSurname1"));
grid.addColumn(new GridColumn('idgridColumn2LC', 'Apellido2', "cSurname2"));
grid.addColumn(new GridColumn('idgridColumn3LC', 'Documento', "cDoc"));
grid.addColumn(new GridColumn('idgridColumn4LC', 'Fecha Nacimiento', "cDate"));
grid.addColumn(new GridColumn('idgridColumn5LC', 'Sexo', "cGender"));
grid.addListener('show',showHandler,this);
var gridStore = new Ext.data.GroupingStore({
root:'matches',
reader: new Ext.data.JsonReader({
.
.
.
.
The code before is the one I'm executing, it obviously continue but the problem is that I get this error from chrome debugger:
Uncaught TypeError: Object #GridPanel has no method 'addListener'
How is it possible? what I'm doing wrong? My library is the 3.4 and I have check the APIs of Ext JS 2.3, 3.4 and 4.1, all of them have this method.
Your gridpanel constructor is not formatted properly per the 3.4 docs.
There should only be a single argument which is a config object (i.e. with config keys and wrapped in curlies {}).
Also full names are customary Ext.grid.GridPanel vs GridPanel. I think you can get around that if you are requiring the Ext.grid.GridPanel.js in your JS but I can't tell if you are doing that.
I probably do not have your arguments mapped to the right configs correctly, but this should give you an idea:
var grid = new Ext.grid.GridPanel({id: 'idGrid', title: '', data: null, width: 250});
You may also want to define the columns and store in the constructor while your at it:
var grid = new Ext.grid.GridPanel({
id: 'idGrid',
title: '',
data: null,
width: 250,
columns: [{
id: 'idgridColumn0LC',
header: 'Nombre',
field: 'cName'
}, {
id: 'idgridColumn1LC',
header: 'Apellido1',
field: 'cSurname1'
}, {
id: 'idgridColumn2LC',
header: 'Apellido2',
field: 'cSurname2'
}, {
id: 'idgridColumn3LC',
header: 'Documento',
field: 'cDoc'
}, {
id: 'idgridColumn4LC',
header: 'Fecha Nacimiento',
field: 'cDate'
}, {
id: 'idgridColumn5LC',
header: 'Sexo',
field: 'cGender'
}],
store: new Ext.data.GroupingStore({
root:'matches',
reader: new Ext.data.JsonReader({
// reader configs
});