At Agira, Technology Simplified, Innovation Delivered, and Empowering Business is what we are passionate about. We always strive to build solutions that boost your productivity.

Handling images in Handsontable

  • By Manikandan Thangaraj
  • October 27, 2016
  • 4710 Views

In this article, we are going to see what is Handsontable, how to integrate Handsontable and most importantly, how to handle images in Handsontable cells. Let’s get into it! For starters, let us see

What is Handsontable?

Handsontable is a free and open-source JavaScript plugin, which is a made up of several spreadsheet components for apps and websites. It is written in JavaScript and not constrained by any external framework. With Handsontable, you can easily do all CRUD operations and provide end-users with an Excel-like experience.
Sometime back, I had this requirement to handle images in the table. To be precise, I had to edit the inline table with images. Although Handsontable provides many cool features like Excel, handling images in Handsontable is quite difficult. In my website (project), I used Handsontable to display user data grid with inline edit feature. The exact requirement was to upload an image from a cell. On searching for a solution I got to know that we can customize cell the editor with the Handsontable. With a custom cell editor, I worked on uploading an image and it was successful.

ALSO READ: 10 Useful Tools For Laravel Development

Let me walk you through the steps I followed:

Installing Handsontable:

There are many ways to install Handsontable. For an instant fix, you can work on jSFiddle.

  1. Install using Bower package manager.
bower install handsontable --save
<script src="/dist/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="/dist/handsontable.full.css"
  1. Download Handsontable from GitHub.
https://github.com/handsontable/handsontable/archive/master.zip
  1. Embed script with CDN URL.
<script src="http://handsontable.com/dist/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="https://docs.handsontable.com/5.0.0/components/handsontable/dist/handsontable.full.css">

Basic Example of Handsontable:

<div id="sample"></div>
var data = [
["", "Audi", "Benz", "Toyota", "Honda"],
["2014", 10, 11, 12, 13],
["2015", 20, 11, 14, 13],
["2016", 30, 15, 12, 13]
];
var container = document.getElementById('sample');
var hot = new Handsontable(container, {
data: data,
minSpareRows: 1,
rowHeaders: true,
colHeaders: true,
contextMenu: true
});

Handling image in Handsontable:

Basically, we can build a new editor from scratch, by creating a new editor class, which inherits from BaseEditor, or if you just want to enhance an existing editor, you can extend its class and override only a few of its methods.
For my process, I will create an UploadEditor which works exactly like regular TextEditor except that it displays an images input instead of the text area. While customising the editor we should override the following methods:

  1. setValue
  2. getValue
  3. focus
  4. close

Let’s begin with the UploadEditor. Following is the code for the same:

var UploadEditor = Handsontable.editors.TextEditor.prototype.extend();
UploadEditor.prototype.createElements = function() {
Handsontable.editors.TextEditor.prototype.createElements.apply(this, arguments);
this.TEXTAREA = document.createElement('input');
this.TEXTAREA.setAttribute('type', 'file');
this.TEXTAREA.setAttribute('id', 'filechange' + this.row);
this.TEXTAREA.className = 'handsontableInput';
this.textareaStyle = this.TEXTAREA.style;
this.textareaStyle.width = 0;
this.textareaStyle.height = 0;
Handsontable.Dom.empty(this.TEXTAREA_PARENT);
this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
hands = this;
$('#filechange' + this.row).change(function() {
var data = new FormData();
data.append('file', $(this).prop('files')[0]);
current = hot.getSourceDataAtRow(hands.row);
$.each(current, function(index, value) {
data.append(index, value);
});
$.ajax({
type: 'POST',
processData: false, // important
contentType: false, // important
data: data,
url: "server.php",
success: function(data) {
$(this).attr('src', data);
hands.TEXTAREA.src = data;
}
});
});
};
UploadEditor.prototype.setValue = function(newValue) {
this.TEXTAREA.src = newValue;
};
UploadEditor.prototype.focus = function() {
this.TEXTAREA.focus();
};
UploadEditor.prototype.getValue = function() {
return this.TEXTAREA.src;
};
UploadEditor.prototype.close = function() {
this.TEXTAREA_PARENT.style.display = 'none';
this.autoResize.unObserve();
if (document.activeElement === this.TEXTAREA) {
this.instance.listen();
}
};

Here I have created a new editor class, that inherits from TextEditor and then override some of its methods to replace the <textarea> with input:file. But, Handsontable cannot handle file input like <textarea>, so we have written some external script to handle file input and you may notice that it calls internal createElements() method, which creates <textarea> node and appends it to DOM during editor initialization.

ALSO READ: Build A Micro-Frontend Application Using Angular Elements

Here is the code to render custom HTML/image in Table Cell:

function coverRenderer (instance, td, row, col, prop, value, cellProperties) {
var escaped = Handsontable.helper.stringify(value),
img;
if (escaped.indexOf('http') === 0) {
img = document.createElement('IMG');
img.src = value;
img.setAttribute('width', '120px');
Handsontable.Dom.addEvent(img, 'mousedown', function (e){
e.preventDefault(); // prevent selection quirk
});
Handsontable.Dom.empty(td);
td.appendChild(img);
}
else {
// render as text
Handsontable.renderers.TextRenderer.apply(this, arguments);
}
return td;
}

Here, did you see that I have written custom render function named coverRenderer()? This will add the image URL into the HTML IMG tag so that the required image will be displayed in the table cell.

Following is the script to render the Handsontable that has been created for the purpose:

var data = [
{"car":"Benz","year":"2001","image_url":"[IMAGE_URL]"},
{"car":"Honda","year":"2005","image_url":"[IMAGE_URL]"}
{"car":"Audi","year":"2000","image_url":"[IMAGE_URL]"}
];
var columns = [{
data: "car",
type: 'text'
}, {
data: "year",
type: "text"
}, {
data: "image_url",
renderer:coverRenderer,
editor: UploadEditor
}
];
var container = document.getElementById('sample');
var hot = new Handsontable(container, {
data: data,
minSpareRows: 1,
rowHeaders: true,
colHeaders: true,
contextMenu: true
});

To save the image into the local server, inside the server.php,

<?php
if(isset($_FILES['file']['tmp_name']))
{
$tmp_name = $_FILES['file']['tmp_name'];
$name = $_FILES['file']['name'];
$type1 = pathinfo($name, PATHINFO_EXTENSION);
$data = file_get_contents($tmp_name);
$image_data = 'data:image/' . $type1 . ';base64,' . base64_encode($data);
list($image_width, $image_height, $image_type, $attr) = getimagesize($tmp_name);
$datas = explode(',', $image_data);
$decode = base64_decode($datas[1]);
$path =  "[PATH_TO_UPLOAD]";
$filename = $name.".".$image_type;
file_put_contents ( $path.$filename , $decode );
return $path.$filename;
}
?>

HTML Code:

<html>
<head>
<script src="http://handsontable.com/dist/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.com/dist/hand sontable.full.css">
</head>
<body>
<div id="sample"></div>
</body>
</html>

Conclusion:

As you can see, the CustomEditor is a cool feature available in Handsontable. Using this feature we can create our own editor. The example that we discussed above provides a clearer picture of how to achieve inline editing and customising the Handsontable plugin to handle images in Handsontable. For more information, refer to Handsontable Documents.
Happy Reading!!!

Looking for a Tech partner to dominate the digital world?

Manikandan Thangaraj

A Passionate full stack developer with 9 years of experience in full stack web application development and expertise in technologies like PHP and Angular. He has huge craze in learning new things about technologies and constantly shares his knowledge with others.