EXTJS 3.3.3 Grid - extjs

I am developing a checkbox grid list with pagination using the EXTJS grid. I need to remember the selected record when the page navigation is performed.
Details:
1) Go to page:1 and selected rows 1,2 and 3.
2) Now navigate to page:2
3) Come back to page:1
4) The rows 1,2 and 3 which are already selected should be shown as selected
Is there is any api in grid which handles this kind of function?
Thanks in advance.

Thanks for your responses. I have achieved my design by implementind a plugin for grid. The plugin looks as,
Ext.namespace('Ext.ux.plugins');
Ext.ux.plugins.CheckBoxMemory = Ext.extend(Object,
{
constructor: function(config)
{
if (!config)
config = {};
this.prefix = 'id_';
this.items = {};
this.idProperty = config.idProperty || 'id';
},
init: function(grid)
{
this.view = grid.getView()
this.store = grid.getStore();
this.sm = grid.getSelectionModel();
this.sm.on('rowselect', this.onSelect, this);
this.sm.on('rowdeselect', this.onDeselect, this);
this.store.on('clear', this.onClear, this);
this.view.on('refresh', this.restoreState, this);
},
onSelect: function(sm, idx, rec)
{
this.items[this.getId(rec)] = true;
},
onDeselect: function(sm, idx, rec)
{
delete this.items[this.getId(rec)];
},
restoreState: function()
{
var i = 0;
var sel = [];
this.store.each(function(rec)
{
var id = this.getId(rec);
if (this.items[id] === true)
sel.push(i);
++i;
}, this);
if (sel.length > 0)
this.sm.selectRows(sel);
},
onClear: function()
{
var sel = [];
this.items = {};
},
getId: function(rec)
{
return rec.get(this.idProperty);
}
});
This plugin was called from gird as,
Ext.grid.Gridpanel({
store: 'someStore',
plugins: [new Ext.ux.plugins.CheckBoxMemory({idProperty: "recordID"})]
});
Hope this helps some one.

I don't think there is. You;d need to store IDs of selected records in some separate store/array and use it to re-apply selections when page is changed.

You could put a MixedCollection Object at the global scope to keep track of these records. This will allow you to store global settings of different object types.

Related

Work with associations on server side; table relationships

I need to do something like this, but on the server side.
http://dev.sencha.com/ext/5.1.0/examples/kitchensink/#binding-associations
My code (when I select one Customers grid row):
selectionchange: function(sm, grid, value, selected, eOpts) {
var storeCustomers = grid.getStore();
var gridOrders = Ext.ComponentQuery.query('#gridOrdersItemId')[0];
var storeOrders = gridOrders.getStore();
var id_customers = storeCustomers.findRecord('id_customers', value); //It does not work; return null
console.log(id_customers ); //null
console.log(value); //undefined
storeOrders.proxy.extraParams = {
'id_customers': id_customers
},
storeOrders.load();
}
For some reason I can not get the value of id_customers when I select a grid record. the result is null.
Any idea how to solve this?
Thanks in advance.
Edited: 06-07-2015
selectionchange: function(sm, grid, record, value, selected, eOpts) {
var storeCustomers = grid.getStore();
var gridOrders = Ext.ComponentQuery.query('#gridOrdersItemId')[0];
var storeOrders = gridOrders.getStore();
var records = grid.getSelectionModel().getLastSelected(record);
storeOrders.proxy.extraParams = {
'id_customers': records.get('id_customers')
},
storeOrders.load();
}
Regarding this:
For some reason I can not get the value of id_customers when I select
a grid record. the result is null.
here is a possible solution:
selectionchange: function(grid, records) {
var storeOrders = Ext.ComponentQuery.query('#gridOrdersItemId')[0]
.getStore();
storeOrders.proxy.extraParams = {
'id_customers': records[0].get('id_customers')
},
storeOrders.load();
}

Refreshing gridpanel after removing newly added record from store

How do I remove a newly added row from a gridpanel? The gridpanel is bound to a store.
I use:
store.remove(record);
store.sync();
It works fine on existing records in the grid, the record is removed from the grid directly, but when I add a record and want to remove it right away, it isn't 'removed' form the grid.
The api is called, so the record is 'removed from the database' and the record is indeed gone when I do e.g. a browser refresh.
Does anyone knows how this works? Thanks in advance.
Store configurations
Ext.define('Iziezie.store.animal.doggywood.animal', {
extend: 'Iziezie.store.animal.animal',
model: 'Iziezie.model.animal.doggywood.animal',
proxy: {
type: 'baseProxy',
api: {
create: '../php/api/doggywood_animals.php?request=create',
read: '../php/api/doggywood_animals.php?request=read',
update: '../php/api/doggywood_animals.php?request=update',
destroy: '../php/api/doggywood_animals.php?request=destroy'
}
}
});
New records is added by form:
var store = gridpanel.getStore();
var model = Ext.ModelMgr.getModel(store.model);
var record = model.create();
store.insert(0, record);
...
frm.loadRecord(record);
On form submit
frm.updateRecord();
var record = frm.getRecord();
record.save();
On remove:
var sm = gridpanel.getSelectionModel();
var record = sm.getLastSelected();
var store = gridpanel.getStore();
store.remove(record);
store.sync();
To force a visual refresh on the grid, you can just call
myGridPanel.getView().refresh();
But this shouldn't be required, the grid should just show whatever is in your store. Can you post a full code sample of what you are doing?
try this to create a new record to grid panel using row editing:
createRecord: function() {
var model = Ext.ModelMgr.getModel('EKOJS.model.m_yourmodel');
var r = Ext.ModelManager.create({
id: '',
text: ''
}, model);
this.getYourgridaliasview().getStore().insert(0, r);
this.getYourgridaliasview().rowEditing.startEdit(0, 0);
},
and to remove the selected record in your grid panel :
deleteRecord: function(dataview, selections) {
var getstore = this.getYourgridaliasview().getStore();
var selection = this.getYourgridaliasview().getSelectionModel().getSelection()[
0];
if (selection) {
Ext.Msg.confirm('Confirmation',
'Are you sure to delete this data: id = "' + selection.data
.id + '"?', function(btn) {
if (btn == 'yes') {
getstore.remove(selection);
getstore.sync();
}
});
}
},
and, the important thing always reload your store after creating record like this :
Ext.Ajax.request({
method: 'POST',
url: '../php/api/doggywood_animals.php?request=create',
params: {
data: jsonData
},
success: function(response) {
e.store.reload({
callback: function() {
var newRecordIndex = e.store.findBy(
function(record, id) {
if (record.get('id') === e.record
.data.id) {
return true;
}
return false;
});
/* me.grid.getView().select(recordIndex); */
me.grid.getSelectionModel().select(
newRecordIndex);
}
});
}
});
The listener of after edit in rowediting plugin i use is like this below :
'afteredit': function(editor, e) {
var me = this;
if ((/^\s*$/).test(e.record.data.id)) {
Ext.Msg.alert('Peringatan', 'Kolom "id" tidak boleh kosong.');
return false;
}
/* e.store.sync();
return true; */
var jsonData = Ext.encode(e.record.data);
Ext.Ajax.request({
method: 'POST',
url: '../php/api/doggywood_animals.php?request=create',
params: {
data: jsonData
},
success: function(response) {
e.store.reload({
callback: function() {
var newRecordIndex = e.store.findBy(
function(record, id) {
if (record.get('id') ===
e.record.data.id
) {
return true;
}
return false;
});
/* me.grid.getView().select(recordIndex); */
me.grid.getSelectionModel().select(
newRecordIndex);
}
});
}
});
return true;
}
May be a little help for you.

Loading store dynamically based on visible page data for Ext.grid.Panel column

Below is a renderer for an Ext.grid.Panel column. Suppose contactStore has 2,000 values in it and all I care about is the name of the record based on the id (value parameter in this case), and my grid only has 25 rows/records in it for the page I'm on. How can I dynamically get the store so that I grab the relevant associated records (based on the foreign key) of the id of my grid column, rather than loading all 2,000 records? Is there a way to load the store and then in the callback, somehow have this "renderer" function display the values after the callback succeeded?
columns: [{
...
}, {
header: 'Contact Name',
flex: 1,
sortable: true,
dataIndex: 'contact_id',
renderer: function(value) {
var contactStore = Ext.StoreManager.lookup('Contacts');
return contactStore.getById(value).get('full_name');
}
}, {
You can adjust the collectData(records, startIndex) in the viewConfig for that:
Ext.create('Ext.grid.Panel', {
(...)
viewConfig: {
//this method needs to be adjusted
collectData: function(records, startIndex) {
var me = this;
//we can use a custom function for this
if (me.onBeforeCollectData) {
me.onBeforeCollectData(records);
}
var data = me.superclass.collectData.call(me, records, startIndex);
return data;
},
onBeforeCollectData: function(records) {
var newExtraParams = [];
var oldExtraParams;
var needToLoadStore = false;
var contactStore = Ext.StoreManager.lookup('Contacts');
if (contactStore) {
oldExtraParams = contactStore.oldExtraParams;
} else {
//don't use autLoad: true, this will be a local store
contactStore = Ext.create('Ext.data.Store', {
storeId:'Contacts',
(...)
});
needToLoadStore = true;
}
for (var x in records) {
//contact_id is read out here
var param = records[x].get('contact_id');
if (param) {
if (needToLoadStore == false && Ext.Array.contains(oldExtraParams, param) == false) {
needToLoadStore = true;
}
newExtraParams.push(param);
}
}
if (needToLoadStore == true) {
//we use this to load the store data => because of async: false property
Ext.Ajax.request({
scope: this,
//this is for synchronous calls
async: false,
url: (...),
method: (...),
params: newExtraParams,
success: function (res, opt) {
var responseObj = Ext.decode(res.responseText, false);
contactStore.loadData(responseObj); //or deeper in the responseObj if needed
contactStore.oldExtraParams = newExtraParams;
}
});
}
}
}
});

ExtJS - Drag column header to other grid

I need keep the default feature of reordering columns and add
possibility drop the column in a second grid, building in the last a list
with the columns of first grid.
I hope has been clear.
I solved the issue extending DropZone. This implementation receive as constructor param the target grid, and this, be in the rbar (docked control) of source grid. The key is set ddGroup to "header-dd-zone-" plus id from source grid. I hope this is useful.
Ext.define('Crud.FilterDropZone', {
extend: 'Ext.dd.DropZone'
, constructor: function() {}
, init: function (grid) {
var me = this;
if (grid.rendered) {
me.grid = grid;
me.ddGroup = 'header-dd-zone-' + grid.up('grid').id;
grid.getView().on({
render: function(v) {
me.view = v;
Crud.FilterDropZone.superclass.constructor.call(me, me.view.el);
},
single: true
});
} else {
grid.on('render', me.init, me, {single: true});
}
}
, getTargetFromEvent: function (e) {
return {};
}
, onNodeDrop: function (nodeData, source, e, data) {
var header = data.header
, store = Ext.getCmp(e.target.id).getStore();
//store.add(new store.RecordType({ property: header.text, value: '', reference: header.dataIndex}));
store.add([[header.text, '', header.dataIndex]]);
}
});

How to make selected item to change class(How to make property observable in backbone)

i want to build simple screen, where list of items in one side and selected item details -on another. when user click on one of the items - its details displayed in 'details' section.
also the selected item in the 'list' section must be decorated with 'active' class.
here is my router code:
var AppRouter = Backbone.Router.extend({
routes:{
"":"list",
"users/:id":"userDetails"
},
list:function () {
this.usersList = new UsersCollection(usersList);/* new UsersCollection()*/
var self = this;
//this.userList.fetch({
// success: function () {
this.UsersListView = new UsersListView({ model: this.usersList });
$('#sidebar').html(this.UsersListView.render().el);
// }
//})//end of fetch
},
userDetails:function (id) {
if(this.usersList){
//unselect prevously selected
if(this.user )this.user.set({'selected':false});
this.user = this.usersList.get(id);
//select current
this.user.set({'selected':true});
//empty refill the items section
this.UsersListView = new UsersListView({ model: this.usersList });
$('#sidebar').empty().html(this.UsersListView.render().el);
if (this.UserDetailsView) this.UserDetailsView.close();
this.UserDetailsView = new UserDetailsView({model:this.user});
$('#content').html(this.UserDetailsView.render().el);
}
else{
}
}
});
So far i managed to set the 'active' item class by emptying and refill the items section html.
Is there any way to observe (like in knockoutjs) the 'selected' property, so once it changes -the change will be visible in html?
code of view:
window.UserListItemView = Backbone.View.extend({
tagName:"li",
template:_.template($('#tpl-user-list-item').html()),
render:function (eventName) {
if(this.model.get('selected')){$(this.el).addClass('active');}
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
Thanks forwards
This is what you're looking for (especially the Events#listenTo method).
So; in your view:
initialize: function() {
// listen to your model
this.listenTo(this.model, 'change:selected', this.updateClass);
},
updateClass: function() {
// something like...
this.$el.toggleClass('active');
}

Resources