Cell types

Registering a cell-type

When you create a custom cell type, a good idea is to assign it as an alias that will refer to this particular type definition. Handsontable defines 9 aliases by default:

  • autocomplete for Handsontable.cellTypes.autocomplete
  • checkbox for Handsontable.cellTypes.checkbox
  • date for Handsontable.cellTypes.date
  • dropdown for Handsontable.cellTypes.dropdown
  • handsontable for Handsontable.cellTypes.handsontable
  • numeric for Handsontable.cellTypes.numeric
  • password for Handsontable.cellTypes.password
  • text for Handsontable.cellTypes.text
  • time for Handsontable.cellTypes.time

It gives users a convenient way for defining which cell type should be used for describing cell properties. User doesn't need to know which part of code is responsible for rendering, validating or editing the cell value, he does not even need to know that there is any functions at all. What is more, you can change the cell behaviour associated with an alias without a need to change the code that defines a cell properties.

To register your own alias use Handsontable.cellTypes.registerCellType() function. It takes two arguments:

  • cellTypeName - a string representing of the cell type object
  • type - an object with keys editor, renderer and validator that will be represented by cellTypeName

If you'd like to register copyablePasswordType under alias copyable-password you have to call:

Handsontable.cellTypes.registerCellType('copyable-password', {
  editor: copyablePasswordEditor,
  renderer: copyablePasswordRenderer,
});

Choose aliases wisely. If you register your cell type under name that is already registered, the target function will be overwritten:

Handsontable.cellTypes.registerCellType('password', {
  editor: copyablePasswordEditor,
  renderer: copyablePasswordRenderer,
});

// Now 'password' alias points to the newly created object, not Handsontable.cellTypes.password

So, unless you intentionally want to overwrite an existing alias, try to choose a unique name. A good practice is prefixing your aliases with some custom name (for example your GitHub username) to minimize the possibility of name collisions. This is especially important if you want to publish your cell type, because you never know aliases has been registered by the user who uses your cell type.

Handsontable.cellTypes.registerCellType('copyable-password', {
  editor: copyablePasswordEditor,
  renderer: copyablePasswordRenderer,
});

// Someone might already registered such alias

Handsontable.cellTypes.registerCellType('my.copyable-password', { editor: copyablePasswordEditor, renderer: copyablePasswordRenderer, }); // That's better.

Using an alias

The final touch is to using the registered aliases, so that users can easily refer to it without the need to now the actual cell type object is.

To sum up, a well prepared cell type object should look like this:

(function(Handsontable){
  var MyEditor = Handsontable.editors.TextEditor.prototype.extend();

  function customRenderer(hotInstance, td, row, column, prop, value, cellProperties) {
    // ...renderer logic
  }

  function customValidator(query, callback) {
    // ...validator logic
    callback(/* Pass `true` or `false` */);
  }

  // Register an alias
  Handsontable.cellTypes.registerCellType('my.custom', {
    editor: MyEditor,
    renderer: customRenderer,
    validator: customValidator,
    // You can add additional options to the cell type based on Handsontable settings
    className: 'my-cell',
    allowInvalid: true,
    // Or you can add custom properties which will be accessible in `cellProperties`
    myCustomCellState: 'complete',
  });

})(Handsontable);

From now on, you can use your cell definition like so:

var hot = new Handsontable(document.getElementById('container'), {
  data: someData,
  columns: [
    {
      type: 'my.custom'
    }
  ]
}); 

Preview of built-in and custom cell types

The below example shows some of the built-in cell types (in other words, combinations of cell renderers and editors) available in Handsontable:

The same example also shows the declaration of custom cell renderers, namely yellowRenderer and greenRenderer.

Anatomy of a cell type

A cell type is a predefined set of cell properties. Cell type defines what renderer, editor or validator should be used for a cell. They can also define any different cell property that will be assumed for each matching cell.

For example, writing:

columns: [{
  type: 'password'
}]

Equals:

columns: [{
  editor: Handsontable.editors.PasswordEditor
  renderer: Handsontable.renderers.PasswordRenderer,
  copyable: false,
}]

Or using custom cell type definition:

Handsontable.cellTypes.registerCellType('custom', {
  renderer: Handsontable.renderers.TextRenderer,
  className: 'my-cell',
  readOnly: true,
  myCustomProperty: 'foo'
})

In Handsontable settings:

columns: [{
  type: 'custom'
}]

Equals:

columns: [{
  editor: false,
  renderer: Handsontable.renderers.TextRenderer,
  className: 'my-cell',
  readOnly: true,
  myCustomProperty: 'foo'
}]

This mapping is defined by files src/cellTypes/

Empty cells

Its worth to mention that values such as '' (empty string), null and undefined are considered empty values. You can use the Handsontable.helper.isEmpty method to check whether a value is considered empty. Cells with empty values are displayed in a similar way for most of the data types (see below).

Empty cells may be treated in differently in different contexts, for example, the ColumnSorting plugin has a sortEmptyCells option responsible for establishing whether empty cells should be sorted like non-empty cells.

Note: Please keep in mind that opening a cell with undefined and null values results in overwriting the original value with an empty string.

Note: Please keep in mind that copying and pasting undefined and null values will result in pasting the empty string.

Edit this page

Tutorial: Cell types