// This is an example of one possible way to make a reusable component (or 'plugin'), consisting of: // * A view model class, which gives a way to configure the component and to interact with it (e.g., by exposing currentPageIndex as an observable, external code can change the page index) // * A custom binding (ko.bindingHandlers.simpleGrid in this example) so a developer can place instances of it into the DOM // - in this example, the custom binding works by rendering some predefined templates using the ko.jqueryTmplTemplateEngine template engine // // There are loads of ways this grid example could be expanded. For example, // * Letting the developer override the templates used to create the table header, table body, and page links div // * Adding a "sort by clicking column headers" option // * Creating some API to fetch table data using Ajax requests // ... etc (function () { // Private function function getColumnsForScaffolding(data) { if ((typeof data.length != 'number') || data.length == 0) return []; var columns = []; for (var propertyName in data[0]) columns.push({ headerText: propertyName, rowText: propertyName }); return columns; } ko.simpleGrid = { // Defines a view model class you can use to populate a grid viewModel: function (configuration) { this.data = configuration.data; this.currentPageIndex = ko.observable(0); this.pageSize = configuration.pageSize || 5; // If you don't specify columns configuration, we'll use scaffolding this.columns = configuration.columns || getColumnsForScaffolding(ko.utils.unwrapObservable(this.data)); this.itemsOnCurrentPage = ko.computed(function () { var startIndex = this.pageSize * this.currentPageIndex(); return ko.utils.unwrapObservable(this.data).slice(startIndex, startIndex + this.pageSize); }, this); this.maxPageIndex = ko.computed(function () { return Math.ceil(ko.utils.unwrapObservable(this.data).length / this.pageSize); }, this); } }; // Templates used to render the grid var templateEngine = new ko.jqueryTmplTemplateEngine(); templateEngine.addTemplate("ko_simpleGrid_grid", "\
${ columnDefinition.headerText } | \ {{/each}}\
---|
${ typeof columnDefinition.rowText == 'function' ? columnDefinition.rowText(row) : row[columnDefinition.rowText] } | \ {{/each}}\