Skip to content

About Custom Templates

jcook-logixml edited this page Nov 13, 2012 · 15 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 : {
    entity : ko.observable(), // this is the original item from your observableArray
    cells: [], // an array of cells in order of your columns
    cellMap: {}, // a map of cells by the column's 'field' name
    rowIndex: number, // the number of the row in the grid
    rowDisplayIndex: number, // if you are paging through data this stays in sync with your current page
    selected: ko.observable() // boolean indicating if the grid row is selected
}

$data ALSO now includes all of the properties of your entity (just pointers straight to those properties). So you can easily just do $data.firstName when you want to access a property of your entity

Each cell in the $data.cells or $data.cellMap has the following properties:

cell : {
    data: ko.observable(), // an observable that holds the value of your object's bound property
    column: // the actual kg.Column class that your cell is bound to
    row: // the actual kg.Row class that your cell belongs to
}

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

<script type="text/html" id="editingCellTemplate">
    <div data-bind="kgCell: { value: 'firstName' }">
        <input type="text" data-bind="value: $data.entity().firstName"/>
    </div>
</script>

Ok great, but what about the kgCell: { value: 'firstName' } binding? This binding will ensure that your cell is aligned correctly in the row and that it is formatted like the other cells (margin, padding, width, etc...)

As of 1.0, cell templates also get 3 shortcut identifiers you can use to make your templates re-usable and easier to understand:

  • $cell --> translates into { value: '<your column's bound property>' }
  • $cellValue --> translates into $data.<your column's bound property>
  • $cellClass --> translates into the cellClass that you have defined in your columnDef for this column

This means the template above could be re-written like:

<script type="text/html" id="editingCellTemplate">
    <div data-bind="kgCell: $cell, attr: { class: '$cellClass' }">
        <input type="text" data-bind="value: $cellValue"/>
    </div>
</script>

These shortcut identifiers should be really handy for making re-usable templates all over your app!

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

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

Row Templates

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

<div data-bind="kgRow: $data">
    <div data-bind="kgCell: { value: 'firstName' }"></div>
    <div data-bind="kgCell: { value: 'lastName' }"></div>
</div>

As before, you will need to use the custom kgRow binding. This binding ensures the correct data is passed throughout the row, and that the row is correctly formatted/rendered in the grid.

Each <div> for the cells can use the kgCell binding. This binding is smart enough to figure out how to display the cell's correct data even if a text or value binding hasn't been coded out.

A special note - you cannot use $cell and its friends in custom Row Templates. If you think about it, it makes sense - but just to clarify.

Clone this wiki locally