ExtJs -> How to create grouped bar chart using 2 related Models (hasmany relationship) - extjs

I am trying to plot a grouped bar chart in ExtJs similar to Sencha's example.
Can you use a field that is a field of the Child Model belonging to the chart's store's Model in the Series xField / yField?
If a "Golfer" Model has many "GolfClubs", is it possible to render a grouped bar chart showing bars for each GolfClub that belongs to a Golfer (each golfer's name will be an axis label)?
In sencha's example the store has all the data in the one record but I'm hoping it can bind automatically to a "hasmany" associated Model?
//Models
Ext.define('GolfClub', {
extend : 'Ext.data.Model',
fields : [{
name : 'ClubType',
type : 'string'
}, {
name : 'Weight',
type : 'float'
}]
});
Ext.define('Golfer', {
extend : 'Ext.data.Model',
requires: ['GolfClub'],
fields : [{
name : 'GolferName',
type : 'string'
}],
hasMany: {model: 'GolfClub', name: 'golfClubs'}
});
//end Models
//Local Data (just to get it working first)
function data(){
var golfers = [];
var rory = Ext.create('Golfer', {
GolferName : 'Rory'
});
var rorysDriver = Ext.create('GolfClub', {
ClubType : 'Driver',
Weight : 80
});
var rorysPutter = Ext.create('GolfClub', {
ClubType : 'Putter',
Weight : 60
});
var rorysSandWedge = Ext.create('GolfClub', {
ClubType : 'SandWedge',
Weight : 50
});
var rorysClubs = rory.golfClubs();
rorysClubs.add(rorysDriver);
rorysClubs.add(rorysPutter);
rorysClubs.add(rorysSandWedge);
golfers.push(rory);
var tiger = Ext.create('Golfer', {
GolferName : 'Tiger'
});
var tigersDriver = Ext.create('GolfClub', {
ClubType : 'Driver',
Weight : 85
});
var tigersPutter = Ext.create('GolfClub', {
ClubType : 'Putter',
Weight : 55
});
var tigersSandWedge = Ext.create('GolfClub', {
ClubType : 'SandWedge',
Weight : 58
});
var tigersClubs = tiger.golfClubs();
tigersClubs.add(tigersDriver);
tigersClubs.add(tigersPutter);
tigersClubs.add(tigersSandWedge);
golfers.push(tiger);
return golfers;
}
//end Local Data
//Local Store
function store1(){
var golferStore = Ext.create('Ext.data.Store', {
model: 'Golfer',
data : data()});
return golferStore;
}
//end Local Store
Ext.onReady(function () {
var chart = Ext.create('Ext.chart.Chart', {
style: 'background:#fff',
animate: true,
shadow: true,
store: store1(),
legend: {
position: 'right'
},
axes: [{
type: 'Numeric',
position: 'bottom',
fields: ['golfClubs.Weight']
}, {
type: 'Category',
position: 'left',
fields: ['GolferName'],
title: 'Golfer'
}],
series: [{
type: 'bar',
axis: ['bottom'],
xField: ['golfClubs.Weight'],//Is that how you bind to child record?
yField: ['GolferName']
}]
});
var win = Ext.create('Ext.Window', {
width: '100%',
height: '100%',
title: 'Breakdown of Golfers and their Clubs..',
autoShow: true,
layout: 'fit',
items: chart
});
});
Cheers,
Tom.

This has been answered in the Sencha forum in case anyone was interested with this question.
The chart's store will need to have all of the data / records populated within the store (-vs- the store being populated with parent records with each having its own associated set of child records). So, I'm afraid what you're wanting to do you can't do directly.
Answer from Sencha Support Team Member
The solution seems to be the merging of parent and child Model's fields into a new Model that can be used in the chart's store combined with groupField and extending series.
Ext.define('Result', {
extend: 'Ext.data.Model',
fields: [
{ name: 'state', type: 'string', mapping:0 },
{ name: 'product', type: 'string', mapping:1 },
{ name: 'quantity', type: 'int', mapping:2 }
]
});
var store = Ext.create('Ext.data.ArrayStore', {
model: 'Result',
groupField: 'state',
data: [
['MO','Product 1',50],
['MO','Product 2',75],
['MO','Product 3',25],
['MO','Product 4',125],
['CA','Product 1',50],
['CA','Product 2',100],
['WY','Product 1',250],
['WY','Product 2',25],
['WY','Product 3',125],
['WY','Product 4',175]
]
});
Ext.define('Ext.chart.series.AutoGroupedColumn', {
extend: 'Ext.chart.series.Column',
type: 'autogroupedcolumn',
alias: 'series.autogroupedcolumn',
gField: null,
constructor: function( config ) {
this.callParent( arguments );
// apply any additional config supplied for this extender
Ext.apply( this, config );
var me = this,
store = me.chart.getStore(),
// get groups from store (make sure store is grouped)
groups = store.isGrouped() ? store.getGroups() : [],
// collect all unique values for the new grouping field
groupers = store.collect( me.gField ),
// blank array to hold our new field definitions (based on groupers collected from store)
fields = [];
// first off, we want the xField to be a part of our new Model definition, so add it first
fields.push( {name: me.xField } );
// now loop over the groupers (unique values from our store which match the gField)
for( var i in groupers ) {
// for each value, add a field definition...this will give us the flat, in-record column for each group
fields.push( { name: groupers[i], type: 'int' } );
}
// let's create a new Model definition, based on what we determined above
Ext.define('GroupedResult', {
extend: 'Ext.data.Model',
fields: fields
});
// now create a new store using our new model
var newStore = Ext.create('Ext.data.Store', {
model: 'GroupedResult'
});
// now for the money-maker; loop over the current groups in our store
for( var i in groups ) {
// get a sample model from the group
var curModel = groups[ i ].children[ 0 ];
// create a new instance of our new Model
var newModel = Ext.create('GroupedResult');
// set the property in the model that corresponds to our xField config
newModel.set( me.xField, curModel.get( me.xField ) );
// now loop over each of the records within the old store's current group
for( var x in groups[ i ].children ) {
// get the record
var dataModel = groups[ i ].children[ x ];
// get the property and value that correspond to gField AND yField
var dataProperty = dataModel.get( me.gField );
var dataValue = dataModel.get( me.yField );
// update the value for the property in the Model instance
newModel.set( dataProperty, dataValue );
// add the Model instance to the new Store
newStore.add( newModel );
}
}
// now we have to fix the axes so they work
// for each axes...
me.chart.axes.each( function( item, index, len ) {
// if array of fields
if( typeof item.fields=='object' ) {
// loop over the axis' fields
for( var i in item.fields ) {
// if the field matches the yField config, remove the old field and replace with the grouping fields
if( item.fields[ i ]==me.yField ) {
Ext.Array.erase( item.fields, i, 1 );
Ext.Array.insert( item.fields, i, groupers );
break;
}
}
}
// if simple string
else {
// if field matches the yField config, overwrite with grouping fields (string or array)
if( item.fields==me.yField ) {
item.fields = groupers;
}
}
});
// set series fields and yField config to the new groupers
me.fields,me.yField = groupers;
// update chart's store config, and re-bind the store
me.chart.store = newStore;
me.chart.bindStore( me.chart.store, true );
// done!
}
})
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
legend: {
position: 'right'
},
axes: [
{
type: 'Numeric',
position: 'left',
fields: ['quantity'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Quantity',
grid: true,
minimum: 0
},
{
type: 'Category',
position: 'bottom',
fields: ['state'],
title: 'State'
}
],
series: [
{
type: 'autogroupedcolumn',
axis: 'left',
highlight: true,
xField: 'state',
yField: 'quantity',
gField: 'product'
}
]
});
Please see here

And as Sencha Fiddle for trying it out: https://fiddle.sencha.com/#fiddle/207

Related

Update Grid Store on Row Editing

I am trying to update the store on RowEditing Update click
Added a Listeners as
listeners: {
'edit': function (editor, e) {
alert('Row Updating');
}
}
Alert is firing on UPdate click so tried to update the store now as below
1.var rec = e.record;
e.store.sync();
2. var timeGrid = this.up('grid');
timeGrid.store.sync();
3. Ext.ComponentQuery.query('#gdItemId')[0].store.sync();
4. this.store.sync();
All the above is failing to update the changed records to store.
It is throwing error as -
Unhandled exception at line 1984, column 17
0x80004005 - JavaScript runtime error: unknown exception
What would be the reason? Please suggest me, how can i update the data here.
Updating :
Adding complete code -
Ext.define('TimeModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'stop_type_id', type: 'int' }
]
});
----------------------
var storeStop = new Ext.data.SimpleStore({
fields: ["value", "text"],
data: [
[1, "Delivery"],
[2, "Pickup"]
]
});
---------------------------
var comboBoxStopRenderer = function (comboStop) {
return function (value) {
var idx = comboStop.store.find(comboStop.valueField, value);
var rec = comboStop.store.getAt(idx);
return (rec === null ? '' : rec.get(comboStop.displayField));
};
}
------------------------
var comboStop = new Ext.form.ComboBox({
store: storeStop,
valueField: "value",
displayField: "text"
});
xtype: 'grid',
itemId: 'gdTimeCommitmentItemId',
store: {
type: 'webapi',
api: {
read: 'api/Report/GetTime'
},
autoLoad: false,
},
columns: [
{
text: 'Stop Type', dataIndex: 'stop_type_id', width: '12%', editor: comboStop, renderer: comboBoxStopRenderer(comboStop)
}
],
plugins: [rowEditingTime],
tbar: [
{
text: 'Add',
handler: function () {
rowEditingTime.cancelEdit();
var timeGrid = this.up('grid');
var r = Ext.create('TimeModel', {
stop_type_id: 1
});
timeGrid.store.insert(0, r);
rowEditingTime.startEdit(0, 0);
}
} ],
listeners: {
'edit': function (editor, e) {
//alert('Updating');
//var rec = e.record;
//e.store.sync();
//var timeGrid = this.up('grid');
//timeGrid.store.sync();
// Ext.ComponentQuery.query('#gdTimeCommitmentItemId')[0].store.sync();
//this.store.sync();
}
}
Include your store proxy class in your question. I think you didn't created your store proxy correctly.
example Store proxy for the Sync
proxy :
{
type : 'ajax',
reader :
{
root : 'data',
type : 'json'
},
api :
{
read : '/ExampleService.svc/students/',
create: '/ExampleService.svc/createstudentbatch/',
update : '/ExampleService.svc/updatestudentbatch/',
destroy : '/ExampleService.svc/deletestudentbatch/'
},
actionMethods :
{
destroy : 'POST',
read : 'GET',
create : 'POST',
update : 'POST'
}}

Querying on DirectChildrenCount Rally JS SDK

I checked out some other questions posted previously but couldn't find a relevant answer. So here I am posting again: Here's my code:
Ext.create('Rally.data.WsapiDataStore',{
autoLoad: true,
model: 'HierarchicalRequirement',
limit: '500',
fetch: ['ObjectID','DirectChildrenCount','FormattedID'],
filters:[{property: 'DirectChildrenCount', operator: '=', value: 0}], //tried both "0",'0'
listeners: {
load: function(store,data,success){
var data_length = data.length;
console.log("Number = ", data);
}
}
});
Result is an empty array. Furthermore, the result did not contain the field "DirectChildrenCount" at all, even though I am fetching it.
I tried your code without any changes, and it returned 300+ items. DirectChildrenCount was included in the result. It was tested against "2.0rc2" and "2.0rc1" with the same result. Here is screenshot from Chrome's DevTools:
Here is another short app where a grid of stories updated since yesterday is built, filtered by the same condition.
{property: 'DirectChildrenCount', operator: '=', value: 0}
js file is below:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
var millisecondsInDay = 86400000;
var currentDate = new Date();
var startDate = new Date(currentDate - millisecondsInDay);
var startDateUTC = startDate.toISOString();
Rally.data.ModelFactory.getModel({
type: 'UserStory',
success: function(model) {
this.grid = this.add({
xtype: 'rallygrid',
itemId: 'grid',
model: model,
columnCfgs: [
'FormattedID',
'Name',
'Owner',
'LastUpdateDate'
],
storeConfig: {
filters: [
{
property: 'LastUpdateDate',
operator: '>',
value: startDateUTC
},
{
property: 'DirectChildrenCount',
operator: '=',
value: 0
},
]
}
});
},
scope: this
});
console.log('items updated since', startDateUTC);
}
});

How to find grid array in the browser ExtJs

Suppose if i have created a grid store like this
var store = Ext.create('Ext.data.ArrayStore', {
fields:['id','title', 'director', 'released', 'genre','tagline', 'price', 'available'],
data: [
[
1,
"Office Space",
"Mike Judge",
"1999-02-19",
1,
"Work Sucks",
"19.95",
1
],
[
3,
"Super Troopers",
"Jay Chandrasekhar",
"2002-02-15",
1,
"Altered State Police",
"14.95",
1
]
]
});
when i run it on browser i could not see anything because it has already been saved in the browser's memory , we need to display it to the the grid to see those data.
if i am editing the grid in the browser using editors plugin, so how can i see the changes made to the grid store? how to see it ?
You can add storeId to the store and then you can use the following global function:
Ext.StoreManager.lookup('storeId');
with this function you can always get the store from anywhere.
the gridpanel has the edit( editor, e, eOpts ) event which can be used after editing is complete.
Example:
var store = Ext.create('Ext.data.ArrayStore', {
storeId: 'gridStore',
(...)
});
var grid = Ext.create('Ext.grid.Panel', {
store: store,
(...),
listeners: {
edit: function(editing, e, eOpts) {
var record = e.record;
console.log('Changes on this record: ', e.record.getChanges());
console.log('Original value: ', (editing.ptype == 'cellediting' ? e.originalValue : e.originalValues));
console.log('New value: ', (editing.ptype == 'cellediting' ? e.value : e.newValues));
}
}
});
//for save on a toolbar
var button = Ext.create('Ext.button.Button', {
text: 'Save',
(...),
handler: function() {
var gridStore = Ext.StoreManager.lookup('gridStore');
console.log('all added, but not synchronized records: ', gridStore.getNewRecords());
console.log('all edited, but not synchronized records: ', gridStore.getUpdatedRecords());
console.log('all modified(added and edited), but not synchronized records:', gridStore.getModifiedRecords());
console.log('all removed, but not synchronized records:', gridStore.getRemovedRecords());
}
});
I'd say it depend.
First, to display you store in a grid, it should be something like this (simplified), following your code:
var grid = Ext.create('Ext.grid.Panel', {
title: 'Test',
store: store,
columns: [
{ text: 'title', dataIndex: 'title' },
{ text: 'director', dataIndex: 'director', flex: 1 }
],
height: 200,
width: 400
});
var MyWindow = Ext.create('widget.window',{width:400,height:200,items:[grid]});
MyWindow.show();
You assigned your store to a local variable "store". Normaly, if you use that store in a grid, and you make changes in that grid, it should reflect in the store.
When you make it editable with the editable grid plugin, changes are directly writen in the store, so this should work:
var currentStoreContent = store.data.items;
or, from the grid:
var currentStoreContent = grid.getStore().data.items

Extjs Chart numeric y-axis as integer

I'm trying to display the numeric y-axis as integer... without luck, always shows decimals.
Please if you found a way to do this reply to me. You can find the code here for easy testing: http://jsfiddle.net/adriansky/4uY7H/
var store1 = Ext.create('Ext.data.Store', {
fields: ['name', {name: 'people', type: 'integer' }],
data:[
{"name":"jan", "people":13},
{"name":"feb", "people":12},
{"name":"mar", "people":12},
{"name":"apr", "people":13},
{"name":"may", "people":12},
{"name":"june", "people":13}
]
});
var chart = Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: '80%',
height: '80%',
store: store1,
axes: [{
type: 'Numeric',
position: 'left',
fields: ['people'],
}, {
type: 'Category',
position: 'bottom',
fields: ['name'],
}],
series: [{
type: 'line',
axis: 'left',
xField: 'name',
yField: 'people',
}]
});
I did this, it took me a while
you have to redefine the whole y-axis, recalculate majorunits etc..
lets assume your chart is called monkeyChart,
once your chart is built, just call monkeyChart.setYAxis(..)
monkeyChart.setYAxis(createNumericAxis(min, max, optCfg));
createNumericAxis: function(start, end, optCfg) {
var cfg = {
majorUnit: calculateMajorUnit(start, end)
};
Ext.apply(cfg, optCfg)
return new Ext.chart.NumericAxis(cfg);
},
calculateMajorUnit: function(min, max){
if(min == undefined) min = 0;
if(max == undefined) max = 20;
var dif = max - min;
var interval = dif / 20;
var intervals = [1,2,5,10,20,50,100,200,500];
for (var i = 0; i < intervals.length; i++) {
if(interval <= intervals[i]){
interval = intervals[i];
break;
}
}
return interval;
},
of course you have to adjust the numbers as you like, eg the intervals you want to see (I did this way so I can have a different density depending on the values)
also if you don't know min and max beforhead you can just pass undefined for both, and an empty object as optCfg
give it a try, I wrote it long time ago I might have missed something now
Try to add the following on your Numeric axes:
label: {
renderer: function (v) {
return v.toFixed(0);
}
}
Then, you can also add the minimum and maximum config for that axes. Example:
minimum : 0
Or on controller:
myChart.axes.items[0].maximum = NaN;
myChart.axes.items[0].minimum = 0;
Values depend on your data or your display preferences.
my previous answer was for ext js 3.4
in your case if you use both
majorTickSteps: 1,
minimum: 0,
seems working
http://jsfiddle.net/alezx/vu5pL/
You can try this:
http://jsfiddle.net/4uY7H/2/
axes: [{
type: 'Numeric',
position: 'left',
fields: ['people'],
decimals: 0,
majorTickSteps: 1,
}, {
type: 'Category',
position: 'bottom',
fields: ['name'],
}],
check the doc for Ext.chart.axis.Numeric and Ext.chart.axis.Axis
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.chart.axis.Axis

extjs 4.1.0 Checkcolumn with grouping plagin - how to make all checkboxes in a group (not grouped checkboxes) to be checked or unchecked together?

I have a grid and use rowactions grouping plugin to have an action button in the grouping header. The fist visible column in the grid is a checkbox column. I need to make the checkboxes in the same group behave the same way. 1) if a user checks one of the checkboxes, all boxes in the same group has to be checked. 2) Also I need to look at another field in the same row and if it doesn't have a value, disable checkboxes (all in the same group), otherwise all checkboxes should be enabled.
I also tried xtype:checkbox. For #1 I just cannot figure out how to get the siblings. I tried using the checkchange - I could get a record there - but I don't know how to get other records from the same group. For #2 - how do I get the record - I need to check one of the values and set the ckeckbox enabled/disabled.
Any ideas?
Thank you.
EDIT: for #2 I went with disable checkcolumn for some rows answer here
This is my index.cshtml
<script type="text/javascript">
Ext.require([
'Ext.container.Viewport',
'Ext.grid.*',
'Ext.util.*',
'Ext.Date.*',
'Ext.ux.CheckColumn',
'ACTGRID.ui.GroupPanelGrid'
]);
Ext.onReady(function () {
initialize();
});
function initialize() {
Ext.Ajax.timeout = 60000; // 60 seconds
var myGrid = Ext.create('ACTGRID.ui.GroupPanelGrid');
var viewport = Ext.create('Ext.container.Viewport', {
layout: 'border',
items: [{
region: 'center',
title: 'Grid',
items: myGrid }]
});
};
</script>
This is the GroupPanelGrid.js:
Ext.Date.patterns = {
ISO8601Long: "Y-m-d H:i:s",
ISO8601Short: "Y-m-d",
ShortDate: "n/j/Y",
LongDate: "l, F d, Y",
FullDateTime: "l, F d, Y g:i:s A",
MonthDay: "F d",
ShortTime: "g:i A",
LongTime: "g:i:s A",
SortableDateTime: "Y-m-d\\TH:i:s",
UniversalSortableDateTime: "Y-m-d H:i:sO",
YearMonth: "F, Y"
};
Ext.define('ACTGRID.ui.TransactionsLateModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Id', type: 'int' },
{ name: 'Approval', type: 'boolean' },
{ name: 'ErrorComment', type: 'string' },
{ name: 'ErrorSource', type: 'string'},
{ name: 'RecordDate', type: 'date', dateFormat: 'MS' }],
idProperty: 'Id'
});
Ext.define("ACTGRID.ui.GroupPanelGrid", {
extend: "Ext.grid.Panel",
requires: ['ACTGRID.ui.TransactionsLateModel',
'Ext.ux.grid.RowActions',
'Ext.grid.feature.Grouping'],
initComponent: function () {
var me = this;
me.features = [Ext.create('Ext.grid.feature.Grouping', {
groupHeaderTpl: 'Grouping Header: {name} ({rows.length}
Item{[values.rows.length > 1 ? "s" : ""]})',
enableGroupingMenu: false })];
me.columns = me.buildColumns();
me.store = Ext.create('Ext.data.Store', {
model: 'ACTGRID.ui.TransactionsLateModel',
remoteSort: true,
storeId: 'TransactionsLateStoreId',
autoLoad: true,
buffered: true,
autoSync: true,
groupField: 'RecordDate',
pageSize: 70,
proxy: {
type: 'rest',
timeout: 600000,
url: '/Home/ActionsGrid/',
reader: {
type: 'json',
root: 'transaction',
totalProperty: "Total"
},
writer: {
type: 'json',
root: 'transaction'
}
}
});
me.autoSizeColumns = true;
me.autoScroll = true;
me.forcefit = true;
me.callParent(arguments);
},
buildColumns: function () {
var me = this;
return [
{
xtype: 'rowactions', hidden: true, hideable: false,
actions: [{}],
keepSelection: true,
groupActions: [{
iconCls: 'icon-grid',
qtip: 'Action on Group',
align: 'left',
callback: function (grid, records, action, groupValue) {
var rec = [].concat(records);
/*does something unrelated*/
}
}]
},
{
text: 'Approval', dataIndex: 'Approval', sortable: true,
width: 50,
xtype: 'checkcolumn',
listeners: {
checkchange: function (column, recordIndex, checked) {
var record = me.getStore().data.items[recordIndex].data;
/* Do something here? - How do I get all the siblings */
},
beforerender: function (e, eOpts) {
/* How do I check another cell in this row to see if it has a value
And disable the ckeckbox and set it read only? */
}
}
},
{ text:'ErrorComment', dataIndex: 'ErrorComment' },
{ text:'ErrorSource', dataIndex: 'ErrorSource'},
{ text:'RecordDate', dataIndex: 'RecordDate', renderer: Ext.util.Format.dateRenderer (Ext.Date.patterns.ShortDate)}];
},
height: 600,
width: 'auto'
});
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
[AcceptVerbs(HttpVerbs.Get)]
[ActionName("ActionsGrid")]
public ActionResult GetActionsGrid()
{
DetailsViewModel model = new DetailsViewModel();
List<ExtJsTreeGrid.Models.ActionGrid> ActionsFromDB = model.GetActionsGrid();
model.transaction = ActionsFromDB;
model.success = true;
return Json(model, JsonRequestBehavior.AllowGet);
}
[AcceptVerbs(HttpVerbs.Put)]
[ActionName("ActionsGrid")]
public ActionResult SetActionsGrid()
{
// do something
}
}
Model:
public class ActionGrid
{
public Int32 Id { get; set; }
public bool Approval { get; set; }
public string ErrorComment { get; set; }
public string ErrorSource { get; set; }
public DateTime RecordDate { get; set; }
}
public class DetailsViewModel
{
public List<ActionGrid> transaction = new List<ActionGrid>();
public bool success = true;
public List<ActionGrid> GetActionsGrid()
{
return new List<ActionGrid> {
new ActionGrid { Id = 1,
Approval = true,
ErrorComment = "Comment",
ErrorSource = string.Empty,
RecordDate = new DateTime(1979, 11, 23)
},
new ActionGrid { Id = 5,
Approval = true,
ErrorComment = "Comment",
ErrorSource = "brodas",
RecordDate = new DateTime(1979, 11, 23)
},
new ActionGrid { Id = 6,
Approval = true,
ErrorComment = "Comment",
ErrorSource = string.Empty,
RecordDate = new DateTime(1979, 11, 23)
},
new ActionGrid { Id = 7,
Approval = true,
ErrorComment = string.Empty,
ErrorSource = "brodas",
RecordDate = new DateTime(1979, 11, 23)
},
new ActionGrid { Id = 2,
Approval = true,
ErrorComment = string.Empty,
ErrorSource = string.Empty,
RecordDate = new DateTime(1980, 05, 20)
},
new ActionGrid { Id = 3,
Approval = true,
ErrorComment = "Comment",
ErrorSource = "brodas",
RecordDate = new DateTime(1995, 01, 12)
},
new ActionGrid { Id = 4,
Approval = true,
ErrorComment = string.Empty,
ErrorSource = string.Empty,
RecordDate = new DateTime(2010, 09, 02)
},
new ActionGrid { Id = 8,
Approval = true,
ErrorComment = string.Empty,
ErrorSource = "brodas",
RecordDate = new DateTime(2010, 09, 02)
},
new ActionGrid { Id = 9,
Approval = true,
ErrorComment = "Comment Errors",
ErrorSource = string.Empty,
RecordDate = new DateTime(2010, 09, 02)
},
new ActionGrid { Id = 10,
Approval = true,
ErrorComment = "Comment Errors",
ErrorSource = "brodas",
RecordDate = new DateTime(2010, 09, 02)
},
new ActionGrid { Id = 11,
Approval = true,
ErrorComment = string.Empty,
ErrorSource = "brodas",
RecordDate = new DateTime(2010, 09, 02)
}};
}
For requirement #1, the checkchange listener is indeed the right place to implement it.
To get all the records in the group, you need to grab a reference to the grid's store, and then use its query method, with your grouping field, and the value in the checked record.
Here's an example:
checkchange: function(col, index, checked) {
var grid = col.up('tablepanel'),
store = grid.getStore(),
record = store.getAt(index),
group = record.get('group'),
// returns a MixedCollection (not a simple array)
groupRecords = store.query('group', group);
// apply the same check status to all the group
groupRecords.each(function(record) {
record.set('checked', checked);
});
}
For your second requirement, I don't really understand when you want it to happen.
Anyway, the check column doesn't support disabling at the row level, so you'll have to implement that first.
The simplest way to do that is to add a field to your model to hold the disabled state. Let's call it 'disabled'. Then, you need two things.
First, render the checkbox disabled state. For that, let's override the renderer of the check column:
,renderer: function(value, meta) {
// Adding disabled class according to record's checkable
// field
if (meta.record.get('disabled')) {
meta.tdCls += ' ' + this.disabledCls;
}
// calling the overridden method (cannot use callParent
// since we haven't define a new class)
return Ext.grid.column.CheckColumn.prototype.renderer.apply(this, arguments);
}
Next, we need to prevent checking or unchecking disabled records. That can be done in the beforecheckchange event:
,beforecheckchange: function(col, index) {
var grid = col.up('tablepanel'),
store = grid.getStore(),
record = store.getAt(index);
if (record.get('disabled')) {
return false;
}
}
Now, you can just enable/disable a record's checkbox by setting the record's 'disabled' field.
record.set('disabled', true); // enable
record.set('disabled', false); // disable
Complete Example
Here's a complete example that implements your first requirement and, maybe, your second one. If that not what you meant for the second requirement, that should take you almost there...
The example can be seen running in this fiddle.
Ext.widget('grid', {
renderTo: Ext.getBody()
,height: 300
,features: [{ftype: 'grouping'}]
,store: {
proxy: {type: 'memory', reader: 'array'}
,fields: [
'name', // something to see
'group', // grouping field
'checkable', // for req #2
'checked', // for check column
'disabled' // for disabled state
]
,groupField: 'group'
,data: [
['Foo 1', 'foo', true],
['Foo 2', 'foo', false],
['Foo 3', 'foo', true],
['Bar 1', 'bar', false],
['Bar 2', 'bar', true],
['Baz 1', 'baz', false],
['Baz 2', 'baz', false],
['Baz 3', 'baz', true]
]
}
,columns: [{
xtype: 'checkcolumn'
,width: 50
,dataIndex: 'checked'
,listeners: {
checkchange: function(col, index, checked) {
var grid = col.up('tablepanel'),
store = grid.getStore(),
record = store.getAt(index),
group = record.get('group'),
// returns a MixedCollection (not a simple array)
groupRecords = store.query('group', group),
// for req #2
disableGroup = !record.get('checkable');
groupRecords.each(function(record) {
record.set('checked', checked);
// Here's how to disable the group... If that's
// really what you want.
record.set('disabled', disableGroup);
});
}
// Returning false from this listener will prevent the
// check change. This is used to implement disabled
// checkboxes.
,beforecheckchange: function(col, index) {
var grid = col.up('tablepanel'),
store = grid.getStore(),
record = store.getAt(index);
if (record.get('disabled')) {
return false;
}
}
}
,renderer: function(value, meta) {
// Adding disabled class according to record's checkable
// field
if (meta.record.get('disabled')) {
meta.tdCls += ' ' + this.disabledCls;
}
// calling the overridden method (cannot use callParent
// since we haven't define a new class)
return Ext.grid.column.CheckColumn.prototype.renderer.apply(this, arguments);
}
},{
dataIndex: 'name'
,text: "Name"
,flex: 1
},{
dataIndex: 'checkable'
,text: "Checkable"
}]
});
as for my case, i have a separate checkbox outside my gridpanel which controls the selection of the checkcolumn.
//Avoid view update after each row
grid.store.suspendEvents();
grid.store.each(function(rec) {
rec.set('ctrl_select_flag', ctrl.value);
});
grid.store.resumeEvents();
grid.getView().refresh();
ctrl.value refers to the component which controls my checkcolumn selection. ctrl_select_flag refers to the dataIndex of my checkcolumn.

Resources