Skip to content

In this tutorial, you will create a custom cell renderer that displays image URLs as actual images in a Vue 3 application.

Overview

You can declare a custom renderer for the HotTable component by declaring it as a function in the Handsontable options or creating a rendering component.

Find out which Vue 3 versions are supported

Declare a renderer as a function

The following example is an implementation of @handsontable/vue3 with a custom renderer added. It takes an image URL as the input and renders the image in the edited cell.

JavaScript
import { defineComponent } from 'vue';
import { HotTable } from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = defineComponent({
data() {
return {
hotSettings: {
data:
[
['A1', '/docs/img/examples/professional-javascript-developers-nicholas-zakas.jpg'],
['A2', '/docs/img/examples/javascript-the-good-parts.jpg']
],
columns: [
{},
{
renderer(instance, td, row, col, prop, value) {
const img = document.createElement('img');
img.src = value;
img.addEventListener('mousedown', (event) => {
event.preventDefault();
});
td.innerText = '';
td.appendChild(img);
return td;
}
}
],
colHeaders: true,
rowHeights: 55,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation'
}
};
},
components: {
HotTable,
}
});
export default ExampleComponent;
HTML
<div id="example1">
<hot-table :settings="hotSettings"></hot-table>
</div>

Declare a renderer as a Vue 3 component

You can use a Vue 3 component as a custom cell renderer by mounting it into the cell’s TD element from inside the renderer function. Use Vue 3’s render(vnode, container) API to mount the component imperatively and reuse the same component instance across re-renders — Vue patches the existing tree instead of remounting.

The renderer function receives the same arguments as a regular function-based renderer. You build a VNode from your component with h(Component, props) and pass it to render() together with the TD element. To pass static props alongside cell data, merge them into the second argument of h().

JavaScript
import { defineComponent, h, render } from 'vue';
import { HotTable } from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
// A reusable Vue 3 component that renders a cell value as an image.
const ImageCell = defineComponent({
props: {
src: { type: String, required: true },
},
render() {
return h('img', {
src: this.src,
onMousedown: (event) => event.preventDefault(),
});
},
});
// Bridge function that mounts the Vue 3 component into the cell's TD element.
// Vue's `render()` patches the existing tree on subsequent calls, so the
// component instance is reused across re-renders.
function imageComponentRenderer(instance, td, row, col, prop, value) {
const vnode = h(ImageCell, { src: value });
render(vnode, td);
return td;
}
const ExampleComponent = defineComponent({
data() {
return {
hotSettings: {
data: [
['Professional JavaScript for Web Developers',
'/docs/img/examples/professional-javascript-developers-nicholas-zakas.jpg'],
['JavaScript: The Good Parts',
'/docs/img/examples/javascript-the-good-parts.jpg'],
],
columns: [
{},
{
renderer: imageComponentRenderer,
},
],
colHeaders: true,
rowHeights: 55,
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
},
};
},
components: {
HotTable,
},
});
export default ExampleComponent;
HTML
<div id="example2">
<hot-table :settings="hotSettings"></hot-table>
</div>

If your component needs access to a Vue application context — for example, global components, plugins, or provide / inject — create a dedicated app per cell with createApp(Component, props).mount(td) instead of render(). Track the returned app instances so you can call app.unmount() when the grid is destroyed.

Related guides

APIs

Configuration options

Core methods

Hooks

What you learned

  • How to declare a custom renderer function in a Vue 3 application.
  • How to read cell values and render HTML elements — such as images — inside cells.
  • How to assign the renderer to a specific column using the renderer option.
  • How to mount a Vue 3 component as a custom cell renderer with render(vnode, td).

Next steps