-
Notifications
You must be signed in to change notification settings - Fork 12
Datagrid
When it comes to styling, the husky datagrid follows an highly customizable decorator approach. In fact, there are two different decorator types which are used by the datagrid;
View-decorators are responsible for the data rendering, which means rendering the item-container and the items itself. Secondly there are pagination-decorators. These decorators handle the pagination of the datagrid.
Per default, the datagrid offers two view-decorators (table, thumbnail) and one pagination-decorator (dropdown). The view-decorator of an datagrid instance is set by the options.view-property of the datagrid. The pagination-property is set by the options.pagination-property.
Additionally view-decorators can be customized by the datagrid options.viewOptions-property. Analogous the options.paginationOptions-property is passed to pagination-decorator instances.
Well, two view-decorators and one pagination-decorator aren't that highly customizable. But here's the point; the datagrid allows you to use your awesome, non-default, self-programmed decorators.
Beneath, you find everything you need to know, if your planning to write your own datagrid-decorator. Also, there are already bundle-specific external-decorators in contact-bundle (card-view) and media-bundle (masonry-view) which could be helpful while reaching for your (decorator-) dreams.
Providing an external decorator to the datagrid isn't that hard. Basically there are 3 steps before you can start implementing your decorator;
- create the decorator file
A datagrid decorator is a simple javascript-file in its own folder. The recommended path to a view-decorator file is "js/components/example-view/example-view.js". As you can guess, the recommenden path to a pagination-decorator is "js/components/example-pagination/example-pagination.js".
- define the path to your decorator
Decorators are loaded by require.js on demand. Therefore it is necessary to register a require-path to the decorator file before the datagrid can load it.
require.config({
paths: {
'datagrid/decorators/example-view': '../../suluexample/js/components/example-view/example-view'
'datagrid/decorators/example-pagination': '../../suluexample/js/components/example-pagination/example-pagination'
}
});
- pass the decorator to the datagrid
To use your decorator, simply set the options.view/options.pagination-property of your datagrid to your require-path.
this.sandbox.sulu.initListToolbarAndList.call(this, 'key', 'fields',
{
// toolbar-options
},
{
// datagrid-options
view: 'datagrid/decorators/example-view'
pagination: 'datagrid/decorators/example-pagination'
}
);
As you might have suspected, your decorator file has to implement a few methods which are used by the datagrid.
This is the recommended basic structure of an view-decorator file (methods which are used by the datagrid are mentioned at the beginning of the code block):
/**
* @class ExampleView (Datagrid Decorator)
* @constructor
*
* @param {Object} [viewOptions] Configuration object
*
* @param {Boolean} [rendered] property used by the datagrid-main class
* @param {Function} [initialize] function which gets called once at the start of the view
* @param {Function} [render] function to render data
* @param {Function} [addRecord] function to add a new record to the grid
* @param {Function} [removeRecord] function to remove an existing record from the grid
* @param {Function} [extendOptions] function to extend the decorator options
* @param {Function} [selectRecord] function to select an existing record
* @param {Function} [deselectRecord] function to deselct an existing record
* @param {Function} [deselectAllRecords] function to deselect all existing records
* @param {Function} [destroy] function to destroy the view and unbind events
*/
define(function() {
'use strict';
var defaults = {
// define your default options here
},
constants = {
// define your constants (e.g. dom-selectors) here
},
templates = {
// define your underscore-templates here
},
/**
* Apply datagrid-content-filters on the given record column by column
* datagrid-content-filters are used to format the raw database-values (e.g. size)
* @param record
* @returns {*}
*/
processContentFilters = function(record) {
var item = this.sandbox.util.extend(false, {}, record);
this.datagrid.matchings.forEach(function(matching) {
var argument = (matching.type === this.datagrid.types.THUMBNAILS) ? this.options.imageFormat : '';
item[matching.attribute] = this.datagrid.processContentFilter.call(
this.datagrid,
matching.attribute,
item[matching.attribute],
matching.type,
argument
);
}.bind(this));
return item;
},
return {
/**
* Initializes the view, gets called only once
* @param {Object} context The context of the datagrid class
* @param {Object} options The options used by the view
*/
initialize: function(context, options) {
this.datagrid = context;
this.sandbox = this.datagrid.sandbox;
this.options = this.sandbox.util.extend(true, {}, defaults, options);
this.rendered = false;
},
/**
* Method to render this view
* @param data object containing the data which is rendered
* @param $container dom-element of the datagrid
*/
render: function(data, $container) {
this.$el = this.sandbox.dom.createElement('<div class="decorator-container"/>');
this.sandbox.dom.append($container, this.$el);
this.renderRecords(data.embedded);
this.rendered = true;
},
/**
* Parses the data and passes it item by item to a render function
* @param records {Array} array with records to render
* @param appendAtBottom
*/
renderRecords: function(records, appendAtBottom) {
this.sandbox.util.foreach(records, function(record) {
var item = processContentFilters.call(this, record);
// render the item to the dom
}.bind(this));
},
/**
* Takes an object with options and extends the current ones
* @param options {Object} new options to merge to the current ones
*/
extendOptions: function(options) {
this.options = this.sandbox.util.extend(true, {}, this.options, options);
},
/**
* Destroys the view
*/
destroy: function() {
// unbind your events here
this.sandbox.dom.remove(this.$el);
},
/**
* Adds a record to the view
* @param record
* @param appendAtBottom
*/
addRecord: function(record, appendAtBottom) {
this.renderRecords([record], appendAtBottom);
},
/**
* Removes a data record from the view
* @param recordId {Number|String} the records identifier
* @returns {Boolean} true if deleted succesfully
*/
removeRecord: function(recordId) {
if (/* record with recordId exists */) {
// remove record from dom
this.datagrid.removeRecord.call(this.datagrid, recordId);
return true;
}
return false;
},
/**
* Selects an item with a given id
* @param id {Number|String} the id of the item
*/
selectRecord: function(id) {
// select record in dom
this.datagrid.setItemSelected.call(this.datagrid, id);
},
/**
* Deselect an item with a given id
* @param id {Number|String} the id of the item
*/
deselectRecord: function(id) {
// deselect record in dom
this.datagrid.setItemUnselected.call(this.datagrid, id);
},
/**
* Deselect all items
*/
deselectAllRecords: function() {
this.sandbox.util.each(this.$items, function(id) {
this.deselectRecord(Number(id));
}.bind(this));
}
};
});
Analogically this is the recommended basic structure of an pagination-decorator file:
/**
* @class InfiniteScrollPagination (Datagrid Decorator)
* @constructor
*
* @param {Object} [paginationOptions] Configuration object
* @param {Number} [options.limit] Data records per page
*
* @param {Function} [initialize] function which gets called once at the start of the view
* @param {Function} [render] function to render data
* @param {Function} [getHeight] function which returns the height of the pagination
* @param {Function} [getLimit] function which returns the height of the pagination
* @param {Function} [destroy] function to destroy the pagination and unbind events
*/
define(function() {
'use strict';
var defaults = {
// define your default options here
},
constants = {
// define your constants (e.g. dom-selectors) here
},
templates = {
// define your underscore-templates here
};
return {
/**
* Initializes the pagination
* @param {Object} context The context of the datagrid
* @param {Object} options The options used by this pagination
*/
initialize: function(context, options) {
this.datagrid = context;
this.sandbox = this.datagrid.sandbox;
this.options = this.sandbox.util.extend(true, {}, defaults, options);
},
* Method to render the pagination
* @param data object containing the data which is rendered
* @param $container dom-element of the datagrid
*/
render: function(data, $container) {
this.$el = this.sandbox.dom.createElement('<div class="pagination-container"/>');
this.data = data;
// render your pagination and bind your events
},
/**
* Returns the total height of the pagination
* @returns {number}
*/
getHeight: function() {
// return the height of your pagination-container
},
/**
* Returns the pagination page size
* @returns {Number} current limit
*/
getLimit: function() {
return this.options.limit;
},
/**
* Destroys the pagination
*/
destroy: function() {
// unbind your events here
this.sandbox.dom.remove(this.$el);
},
};
});