The subject is a little confusing, but here is what I'm trying to do:
I have created a KnockoutJS custom binding to display a grid on my page. This works well, I followed the SimpleGrid model on the site. However, some of my fields are dates, booleans, etc. I would like to use a custom binding to transform a date using the time ago plugin, etc. Before I built the grid I would simply assign the custom binding in the grid. Now that I am using a "reusable" grid binding I want to be able to pass in (as part of my column definitions) a list of bindings and values to assign in the template for the header and cells of my grid.
Here's the HTML in my page:
<div data-bind="grid: grid" />
Here's the HTML Page View Model:
var tenantsViewModel = {
navigateDetails: function (tenant) {
document.location = '/Tenants/Details/' + tenant.TenantId;
},
navigateDomain: function (tenant) {
window.open("http://" + tenant.Domain);
},
grid: new my.grid({
resource: "system/tenants",
columns: [
{ display: "Tenant", value: "Name", isLink: true },
{ display: "Enabled", value: "IsEnabled", isLink: false },
{ display: "Tenant Since", value: "CreatedOn", isLink: false },
{ display: "Domain", value: "Domain", isLink: true }
]
})
};
tenantsViewModel.grid.update();
ko.applyBindings(tenantsViewModel);
Here's my custom grid binding and template:
// Object
my.grid = function (config) {
var self = this;
self.data = ko.observableArray([]);
self.columns = config.columns;
var resource = config.resource;
my.grid.prototype.update = function () {
// A Wrapper for $.ajax()/JSONP
my.get(resource, function (data) {
self.data(data);
});
};
};
// Templates
var templateEngine = new ko.nativeTemplateEngine();
templateEngine.addTemplate = function (templateName, templateMarkup) {
document.write("<script type=\"text/html\" id='" + templateName + "'>" + templateMarkup + "<" + "/script>");
};
templateEngine.addTemplate("merlin_grid", "\
<table class=\"data\">\
<thead>\
<tr data-bind=\"foreach: columns\">\
<th data-bind=\"text: display\"></th>\
</tr>\
</thead>\
<tbody data-bind=\"foreach: data\">\
<tr data-bind=\"foreach: $parent.columns\">\
<td data-bind=\"css: { link: isLink },text: typeof value == 'function' ? value($parent) : $parent[value] \"></td>\
</tr>\
</tbody>\
</table>");
// Grid: Convert element into a full blown grid component
ko.bindingHandlers.grid = {
init: function () {
return { controlsDescendantBindings: true };
},
update: function (element, viewModelAccessor, allBindingsAccessor) {
var viewModel = viewModelAccessor(), allBindings = allBindingsAccessor();
while (element.firstChild)
ko.removeNode(element.firstChild);
var gridTemplateName = allBindings.gridTemplate || "merlin_grid";
var gridContainer = element.appendChild(document.createElement("DIV"));
ko.renderTemplate(gridTemplateName, viewModel, { templateEngine: templateEngine }, gridContainer, "replaceNode");
}
};
Is there an easy way to do this?
Thanks
I was unable to get this to work. I've got a question out to the KnockoutJS user group as well. If they ever respond I'll post the result here.