Does anyone have/know of a working example of a moving rows within an EditorGridPanel (or know why it's not working for me)?
I've found few examples, and the ones I've found use this approach:
// calculate the new index, then remove the record from the store, and re-insert it at the new index
grid.getStore().remove(record);
grid.getStore().insert(index, record);
In my case this fails. It looks good in the grid, but 2 DELETE http requests actually get sent to the server, and no PUT. This becomes evident when I reload the page - the moved row has actually been deleted.
He're the basic config of my store:
var remoteJsonStore = new Ext.data.JsonStore({
storeId: 'colStore',
autoDestroy: false,
autoSave: true,
proxy: new Ext.data.HttpProxy({url:'/exercises/collect/data_rows'}),
restful: true,
format: 'json',
disableCaching: false,
autoLoad: true,
writer: new Ext.data.JsonWriter({
encode: false
}),
root: 'data',
idProperty: 'data_row_id',
fields: recordFields,
baseParams:{section_id:GridUtils.properties[gridId]['section_id']},
listeners:{
exception:function(misc){
// stuff....
},
beforewrite:function(store, action, rs, options, arg){
this.baseParams["position"]=rs.rowIndex;
},
beforesave:function(store, data){
// stuff.... }
}
}
});
I had a similar problem when implementing a DnD reordering view. The problem is that the store marks every remove()d record for delete, even if you re-insert it.
Reading the source of Ext.data.Store's remove() method, I found a solution:
remove: function(records, /* private */ isMove) {
See? We can pass a second boolean agument to tell the store we are just moving the record! But being marked as private and not documented, we should take care when upgrading to a new version of the framework.
So the final solution is:
grid.getStore().remove(record, true); // just moving
grid.getStore().insert(index, record);
ExtJS version: 4.1
Related
using extjs 5.1.0
My issues, when I add value to store of grid and then call store.sync()
inserted row become selected (visually) but I cannot select it for edit or darg&drop row for sorting, only helps reload grid.
here is my store:
var store = Ext.create('Ext.data.ArrayStore', {
model: 'pbxe.module.conference.ConferenceModel',
proxy: {
type: 'direct',
api: {
read: pbxe._conference.read,
create: pbxe._conference.create,
update: pbxe._conference.update,
destroy: pbxe._conference.destroy,
},
reader: {
rootProperty: 'data',
totalProperty: 'totalCount',
successProperty: 'success',
messageProperty: 'message'
},
writer: {
writeAllFields: true,
},
},
autoSync: false,
autoLoad: true,
});
We ran into same problem, seems there is an issue of the Selection Model keeping a map of the records added to the store which can't get "deselected".
So with a bit of brute force:
// WORKAROUND for grid / selection model problem
// after adding multiple new records with Store.sync()
//var grid = grid bound to this store...
myStore.sync(
{
scope: this,
success: function (batch, options) {
var sm = grid.getSelectionModel();
var records = batch.operations[0].getRecords();
if (sm && sm.selected)
{ // deselect does not work as has bug leaves new records in map
sm.selected.map = {}; //wipe clear the selected records map
}
sm.select(records);
}
});
Hope this helps - works for us in Ext JS 5.1.0
UPDATE -
I HAVE ALSO MADE A MOCK IN JSFIDDLE http://jsfiddle.net/mAgfU/371/
AND WITH A FORM PANEL : http://jsfiddle.net/kA6mD/2/
I have the bellow comboox.
When I use the following code to set the form values:
this.form.loadRecord(data);
the entire form is acting ok except from the combo.
instead of giving me the displayField, I get the valueField in the display.
As you can see in the image above, the combo should show the word "Walla" (displayField) instead of "1" (valueField)
Ext.define('App.view.ForeignCombo', {
extend: 'Ext.form.ComboBox',
alias: 'widget.foreigncombo',
queryMode: 'local',
displayField: 'Name',
valueField: 'Id',
editable: false,
matchFieldWidth: false,
constructor: function(config) {
Ext.apply(this, config);
Ext.define('BrnadComboModel', {
extend: 'Ext.data.Model',
fields: ['Id', 'Name']
});
this.store = Ext.create('Ext.data.Store', {
model: 'BrnadComboModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/api/Brand/',
reader: {
type: 'json',
root: 'Results'
}
},
pageSize: 50,
});
this.callParent();
}
}
);
this is how I use it:
{
"xtype": 'foreigncombo'
, "name": 'Brand.Id'
, "fieldLabel": 'Brand.Id'
}
There is no race bewtween the form display and the combo ajax request, the combo store is autoLoad:true, meaning I see that it has already been loaded...
Thanks
I used your fiddle a an example. Place a breakpoint in line 87 (Ext.ComponentQuery.query('comobobox')....), in this fiddle http://jsfiddle.net/kA6mD/9/, and set a watch to Ext.ComponentQuery.query('combobox')[0].store.data.. you'll notice the store has no data. This may be linked to what I mentioned in the comment.
I know there must be a better way of doing this, but what I usually use as a workaround is either load the store at some point before in the app or use a synchronous Ext.Ajax.request and load each record at a time in the store.
As this is a combo for brands I suppose you could load the store before (i.e. app load) and lookup for the store instead of creating a new one each time you create a foreigncombo component, so the first solution should work.
As for the second workaround it should also work, it takes a little bit more coding but its actually pretty easy. It should look something like this...
Ext.Ajax.request({
url:'your/url/',
async:false,
.....
success:function(response){
var records = Ext.JSON.decode(response.responseText);
for(var m=0; m<records.length; m++){
var record = Ext.create('YourBrandModel',{
abbr:records[m].abbr,
name:records[m].name
});
store.add(record);
}
}
})
You should do this as few times as possible as it may slow down the user experience if it gets called everytime you create a "foreigncombo", so checking if this store exists before creating one might be a good idea.
Please take in cosideration that I have not tested this code, so you may have to tweak it a little in order for it to work. But it should get you on tracks.
Ok, so say I have a store server side so we are doing remote everything. Example of stores:
Ext.create('Ext.data.Store', {
model: 'MyApp.model.ContactModel',
remoteFilter: true,
remoteSort: true,
autoLoad: true,
autoSync: true,
storeId: 'ContactStore-1'
});
Ext.create('Ext.data.Store', {
model: 'MyApp.model.ContactModel',
remoteFilter: true,
remoteSort: true,
autoLoad: true,
autoSync: true,
storeId: 'ContactStore-2'
});
I hit a problem when I do the following:
Ext.getStore('ContactStore-1').insert(0,{'name':'say'});
Ext.getStore('ContactStore-2').insert(0,{'name':'hi'});
What happens is that when I look at the DB I end up having 2 entries. I get 'hi' once and 'say' twice. From the looks of it what is happening is that the first insert statement gets sent and then the second insert statement gets sent but with data from both inserts (I assume it's cause they share the same model and thus the same proxy)
Thoughts on how I can resolve this so that it doesn't auto merge insertion requests?
Model for your viewing pleasure:
Ext.define('MyApp.model.ContactModel', {
extend: 'Ext.data.Model',
idProperty: 'idContact',
fields: [
{
name: 'idContact',
type: 'int'
},
{
name: 'name',
type: 'string'
}
],
proxy: {
type: 'direct',
api: {
create: contact.createRecord,
read: contact.getResults,
update: contact.updateRecords,
destroy: contact.destroyRecord
},
reader: {
type: 'json',
root: 'data'
}
}
});
I think you are not returning the correct data from the server side on the create. If you do not return the id the server created on the first insert, ExtJS will still think your "say" item is a phantom. That is, it has not yet been stored server side.
When you do the second insert, the store will do a sync as you have autosync on. Sync will send ALL pending changes. Since your "hi" item is new that will be sent in a POST as is expected. But since your previous "hi" item does not have a server generated id and is still a phantom, it too will be sent in a POST with your second sync (triggered by the insert).
Basically the server must return the new id with the success result set so that ExtJS knows that the item has been stored by the server. Here's an example from my REST API:
Request has this payload (check Chrome Developer tools network tab).
POST to http://localhost:8081/api/channel?_dc=1372594759864
{"id":0,"number":0,"name":"test"}
This is the server response (200 OK):
{
"result": {
"id": 4, // <- important
"number": 3,
"name": "test",
},
"success": true,
"location": "http://localhost:8081/api/item/4",
"userMessage": null,
"userTitle": "Success",
"devErrors": null
}
All fields in the model are updated by the data in the server response, and as such your hi and say items will get their server id's set. When the id is set, the phantom property is set to false. You can have a look in the Ext.data.Model js-file for the source code for this if you want to dig deeper. :)
In your case you must have idContact in the returned object as that is you idProperty.
If you want to suspend auto sync, do your inserts and sync manually and then turn auto syncs back on you can use SuspendAutoSync and ResumeAutoSync.
The best way to add models to stores in my opinion is to create your model, save it, and on success put it in the store. That requires you to have the proxy in each model. That would look something like this:
var hi = Ext.create('MyApp.model.ContactModel', {
name: 'hi'
});
hi.save({
success: function (record, operation) {
Ext.getStore('ContactStore-1').add(hi);
// You could do your second insert here that is dependent on the first to be completed
},
failure: function (record, operation) {
Ext.MessageBox.alert("Error", "Could not save model at this time...");
},
scope: this
});
In this way you could add your second item in the success handler of the first item's save.
I have grid with 10000 records. I am trying to retrive the grid data by reading the store which populates the grid. But I am not able to read all the data from the store. In stead only 5000 record are being retrieved. Is there a limit ExtJs4? Please find below the code snippet.
enter code here
onDownloadXLS : function(btn, e) {
var store = this.getGridStoreStore();
alert(store.getCount());// This is returning only 5000 rows not 10000.
var records = store.data.items.map(function(r){ return r.data });
}
Ext.define('MyApp.store.GridStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.GridModel',
proxy: {
type: 'ajax',
url: "data/test.json",
reader: {
type: 'json',
root: 'performance'
}
},
sorters: {property: 'uploadedDate', direction: 'DESC'},
groupField: 'uploadedDate',
autoLoad: true
});
The only answer I can give you here is that a browser application should never load that amount of data. You have a design issue if you are forced loading that much data.
You should either use paging or infinite scrolling (with a buffered store) in case of a grid and delegate all sort and search/filter operations to the server.
Basically there is no limitation. See this Sencha example of infinite scrolling with over 6000 records.
I've got a weird problem while using the baseParams in a DirectStore of ExtJs 3.4: The baseParams are NULL, when the API call (using extdirect) is made, although the baseParams are set in the store object. I've checked this by writing the complete store object to the console during "beforeLoad". My store looks like this:
this.store= new Ext.data.DirectStore({
storeId: 'HereComesTheId',
api: {
read: Abc.pluginName.listSomeStuff
},
listeners: {
'load': function (store, records, options) {
Ext.each(records, function (record, index, all) {
if (record.data.selected === true) {
store.fireEvent('someThingsHappened', record, index);
return false;
}
}, this);
}
},
reader: new Ext.data.JsonReader(),
remoteSort: false,
autoLoad: true,
baseParams:{
'param1': Ext.getCmp('Blub').param1,
'param2': '123'
},
});
I've also tried to use setBaseParams(), but it doesn't work, too.
I've used stores several times before and never got a problem like this. Any ideas?
I found the answer by myself: There was a misconfiguration of the Extdirect API, I was calling. The public function in action.class.php was set as
#extdirect-len 0
If the function expects one or more request parameters, you have to set
#extdirect-len 1
and than you have to re-generate the extdirect API. That's it