Skip to content

Instantly share code, notes, and snippets.

@rogersillito
Last active May 13, 2020 14:50
Show Gist options
  • Save rogersillito/1e2e6ba696b81c30f0471229814568aa to your computer and use it in GitHub Desktop.
Save rogersillito/1e2e6ba696b81c30f0471229814568aa to your computer and use it in GitHub Desktop.
A version of the knockout.simpleGrid binding that works in amd (e.g. requirejs). It uses DOM append instead of document.write().
define(['knockout'], function(ko) {
'use strict';
// adapted from: https://github.com/knockout/knockout/blob/gh-pages/examples/resources/knockout.simpleGrid.3.0.js
// 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.unwrap(this.data));
this.itemsOnCurrentPage = ko.computed(function () {
var startIndex = this.pageSize * this.currentPageIndex();
return ko.unwrap(this.data).slice(startIndex, startIndex + this.pageSize);
}, this);
this.maxPageIndex = ko.computed(function () {
return Math.ceil(ko.unwrap(this.data).length / this.pageSize) - 1;
}, this);
}
};
// Templates used to render the grid
var templateEngine = new ko.nativeTemplateEngine();
templateEngine.addTemplate = function(templateName, templateMarkup) {
var scriptTag = document.createElement('script');
scriptTag.type = 'text/html';
scriptTag.id = templateName;
scriptTag.text = templateMarkup;
document.getElementsByTagName('body')[0].appendChild(scriptTag);
};
templateEngine.addTemplate('ko_simpleGrid_grid',
'<table class="ko-grid" cellspacing="0">' +
'<thead>' +
'<tr data-bind="foreach: columns">' +
'<th data-bind="text: headerText"></th>' +
'</tr>' +
'</thead>' +
'<tbody data-bind="foreach: itemsOnCurrentPage">' +
'<tr data-bind="foreach: $parent.columns">' +
'<td data-bind="text: typeof rowText == \'function\' ? rowText($parent) : $parent[rowText]"></td>' +
'</tr>' +
'</tbody>' +
'</table>');
templateEngine.addTemplate('ko_simpleGrid_pageLinks',
'<div class="ko-grid-pageLinks">' +
'<span>Page:</span>' +
'<!-- ko foreach: ko.utils.range(0, maxPageIndex) -->' +
'<a href="#" data-bind="text: $data + 1, ' +
'click: function() { $root.currentPageIndex($data) }, ' +
'css: { selected: $data == $root.currentPageIndex() }">' +
'</a>' +
'<!-- /ko -->' +
'</div>');
// The "simpleGrid" binding
ko.bindingHandlers.simpleGrid = {
init: function() {
return { 'controlsDescendantBindings': true };
},
// This method is called to initialize the node,
// and will also be called again if you change what the grid is bound to
update: function (element, viewModelAccessor, allBindings) {
var viewModel = viewModelAccessor();
// Empty the element
while(element.firstChild)
ko.removeNode(element.firstChild);
// Allow the default templates to be overridden
var gridTemplateName = allBindings.get('simpleGridTemplate') || 'ko_simpleGrid_grid',
pageLinksTemplateName = allBindings.get('simpleGridPagerTemplate') || 'ko_simpleGrid_pageLinks';
// Render the main grid
var gridContainer = element.appendChild(document.createElement('DIV'));
ko.renderTemplate(gridTemplateName, viewModel, { templateEngine: templateEngine },
gridContainer, 'replaceNode');
// Render the page links
var pageLinksContainer = element.appendChild(document.createElement('DIV'));
ko.renderTemplate(pageLinksTemplateName, viewModel, { templateEngine: templateEngine },
pageLinksContainer, 'replaceNode');
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment