About Custom Templates

Steve Rice edited this page Aug 21, 2013 · 16 revisions

If defining columns just isn't giving you the level of flexibility you need, then it's probably time you override one of the default templates that KoGrid uses to render rows and headers.

KoGrid leverages the template engine that Knockout has been configured to use (usually its own native engine if you are unsure what I am talking about).

Cell Templates

The best place to start is to simply override the default cell template that KoGrid uses when it renders rows.

In order to get started writing your own cell template, you need to know what data is being passed to your cell template:

$data : {
    $data: kg.Column: //the column entity
    $parent.getProperty('my.field.Name'): function(), // this function retrieves the value of the column field from your data model for the current row.
    $data.getProperty($parent): function() // this gets the current column's field from the current row and applies the cellFilter to the cell.
    $parent: {{ko binding context}} // The row entity.
    $parent.entity: //your data model 
    selected: ko.observable() // boolean indicating if the grid row is selected
    $userViewModel: {{ko binding context}}// accessor to your viewmodel that you used to instantiate the grid.

An often needed cell template is one that allows editing values in place in the grid:

<!-- Default Cell Template -->
<div data-bind="attr: { 'class': 'kgCellText colt' + $index()}, html: $data.getProperty($parent)"></div>

<!-- Input Cell Template -->
<input type="text" data-bind="attr: { 'class': 'kgCellText colt' + $index()}, value: $parent.entity['myFieldName']"/>


  • Notice how we did not use the getProperty convenience method? That is because getProperty only returns the value, processed through the cellFortmatter option, and not the observable property. If you need the observable property for two-way data binding you need to access your data-model directly through this syntax: $parent.entity['editableField'].
  • attr: { 'class': 'colt' + $index()} is recommended for proper text alignment in the cell but is not required.

Ok great, but what about the kgCellText class? This kgCellText class will ensure that your cell text is aligned correctly and that it is formatted like the other cells (margin, padding, width, etc...)

Once you have defined the custom cell template, you can add it to your colDefs like so:

colDefs: [{ field: 'firstName', displayName: 'First Name', cellTemplate: TemplateAsString }]

Prior to 2.0 the cellTemplates required script element ids for cellTemplates. That is no longer necessary (or supported). You can just pass the template as a string to the column definition. this means you can get the string from anywhere: an ajax call to a partial html file, a document.getElementById().innerHTML or $('#MyTemplateID').html() call using some existing templates, etc...

Row Templates

Row templates work very similarly to cell templates. An example row template would look like:

<div data-bind="foreach: $grid.visibleColumns, css: { 'ui-widget-content': $grid.jqueryUITheme }">
    <div data-bind="attr: { 'class': cellClass() + ' kgCell col' + $index() }, kgCell: $data"></div>

<!-- change the background color of the row based on your datamodel-->
        height: 100%;
        background-color: red;
        font-weight: bold;
<div data-bind="foreach: $grid.visibleColumns, css: { 'errorRow': getProperty('ErrorMessage') }">
    <div data-bind="attr: { 'class': cellClass() + ' kgCell col' + $index() }, kgCell: $data"></div>


  • You can also access $userViewModel from here and anywhere else you create a template to access your personal methods and observables.
  • The binding kgCell: $data {{column}} compiles your cellTemplates/cellFilters automatically. otherwise feel free to make the template however you want.
  • attr: { 'class' : 'col' + $index() } is required to properly align the cell in the row. If you decide not to foreach the columns to create cells, then you can simply assign the proper class like col0 or col3 (zero-based index).
  • css: { 'ui-widget-content': $grid.jqueryUITheme } is not required unless you are using ThemeRoller
  • getProperty('ErrorMessage') if you're not sure, I just check to see if the field has a value that is not null or undefined to apply the class.
  • You can also specify partial html file URLs as templates. Such as: partials/myCellTemplate.html