Skip to content

Instantly share code, notes, and snippets.

@topherfangio
Created July 30, 2012 20:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save topherfangio/3209822 to your computer and use it in GitHub Desktop.
Save topherfangio/3209822 to your computer and use it in GitHub Desktop.
Notes on SlickGrid with Sproutcore
PLEASE NOTE: This is in regards to SlickGrid version 1.4.3; it appears a newer version is available, so your mileage may vary.
Using SlickGrid within Sproutcore requires a few steps:
1) Import the proper files as frameworks
2) Update the Buildfile appropriately
3) Create a basic wrapper class for the functionality you need
1 - So, the basic directory structure I used when importing the frameworks follows. I added two new directories, slickgrid and slickgrid_libs to hold them:
slickgrid
Buildfile <-- This just requires slickgrid_libs (i.e. config :slickgrid, :requires => [ :slickgrid_libs ])
resources
images
sort-asc.gif
sort-desc.gif
stylesheets
slick.columnpicker.css
slick.grid.css
slick.pager.css
slick.columnpicker.js
slick.editors.js
slick.grid.js
slick.model.js
slick.pager.js
slick.remotemodel.js
and
slickgrid_libs
jquery.event.drag-2.0.min.js
jquery.event.drop-2.0.min.js
jquery.jsonp-1.1.0.min.js
jquery.simulate.js
jquery.sparkline.min.js
jquery-ui-1.8.5.custom.min.js
Some of these (like the sparklines) may not be necessary if you do not use that particular feature.
2 - Next, update the project Buildfile to require the files:
config :my_app, :requires => [ :slickgrid ]
3 - Finally, the files below show the basic wrapper that I created. You'll notice that the gridColumnsController and gridDataController are extremely simple. These were basically just a nice way for SproutCore to drop the data. The SlickGridView does the majority of the work. It watches for changes to the columns and data, and then updates the view appropriately. As of now, this destroys the previous grid and recreates it. In my app, this doesn't happen very often, so it isn't a big deal. If performance is an issue, you will probably want to override the view's render() function to be a bit smarter and not recreate the grid every time.
For reference, attached are also some examples of the data that my server returns and what gets stored into the controllers (columns.json and data.json).
"columns":[
{"id":"178", "name":"ID", "field":"list_column_178", "content_type":"Member", "editable":false}
{"id":"179", "name":"Preferred Name", "field":"list_column_179", "content_type":"text", "editable":true}
{"id":"180", "name":"First Name", "field":"list_column_180", "content_type":"text", "editable":true}
{"id":"181", "name":"Middle Name", "field":"list_column_181", "content_type":"text", "editable":true}
{"id":"182", "name":"Last Name", "field":"list_column_182", "content_type":"text", "editable":true}
]
"data":[
{"id":"174828","row_id":"Q1001","list_column_178":"Q1001","list_column_179":"Luke","list_column_180":"Luke","list_column_181":"Porter","list_column_182":"Baxley"},
{"id":"175010","row_id":"Q1003","list_column_178":"Q1003","list_column_179":"Anne","list_column_180":"Anne","list_column_181":"Faith","list_column_182":"Scott"},
{"id":"174868","row_id":"Q1004","list_column_178":"Q1004","list_column_179":"Lucy","list_column_180":"Lucy","list_column_181":"Belle","list_column_182":"Blakeslee"}
]
MyApp.gridColumnsController = SC.Object.create({
});
MyApp.gridDataController = SC.Object.create({
});
MyApp.SlickGridView = SC.View.extend({
_grid: null,
_contextMenu: null,
dataBinding: 'MyApp.gridDataController.content',
columnsBinding: 'MyApp.gridColumnsController.content',
statechartBinding: 'MyApp.statechart',
generateGrid: function() {
var layer = this;
if (!SC.none(layer._grid)) {
layer._grid.destroy();
layer._grid = null;
}
var statechart = this.get('statechart');
var selector = '#' + layer.get('layerId');
var data = this.get('data');
var columns = this.get('columns');
var list_id = 1;
var options = {
editable: true,
enableCellNavigation: true,
enableColumnReorder: true,
forceFitColumns: true
};
if (SC.none(data) || SC.none(columns) || data.length === 0 || columns.length === 0) {
$(selector).html('<center>There is currently no data available for this list.</center>');
return;
}
if (!SC.none(data) && !SC.none(columns)) {
// Ensure the editor columns are properly mapped
columns = columns.map(function(column) {
var new_column = column;
if (!SC.none(column.editor_type)) {
new_column.editor = SC.getPath('window.' + column.editor_type);
}
return new_column;
});
/*
* Override some SlickGrid events to pass them to my statechart
*/
layer._grid = new Slick.Grid(selector, data, columns, options);
layer._grid.onCellChange = function(row_num, column_num) {
var sortedColumns = columns.sortProperty('visible_order');
var row = data[row_num];
var column = sortedColumns[column_num];
statechart.sendAction('updateCellAction', row, column);
};
layer._grid.onColumnsReordered = function() {
var columns = layer._grid.getColumns();
var vo = 0;
if (!SC.none(columns)) {
columns = columns.map(function(column) {
return { id:column.id, visible_order:++vo }
});
statechart.sendAction('reorderColumnsAction', list_id, columns);
}
}
layer._grid.onSort = function(column, ascending) {
statechart.sendAction('sortListAction', { column_id: column.id, ascending: ascending });
}
}
MyApp.currentGridController.set('content', layer._grid);
}.observes('columns', 'data')
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment