Jewell Jewell - 22 days ago 5
Javascript Question

Handsontable Header Search, Input Text, is Cleared Intermittently on Scroll

I'm having issue with maintaining search terms in text input fields that I have added to the HoT headers. If I enter a search term and scroll down this term often gets cleared. I think this may relate to HoT header freeze behaviour upon scroll.

Steps to reproduce


  1. HoT container with some data and colHeaders. Include HTML input text element in colHeaders for each/any column

  2. Enter some text into the input text box

  3. Scroll down the page until data is cleared. If the effect is not seen reload the page and try again until behaviour is observed.
    Note you may need to reduce the page size to facilitate an adequate scroll to observe the data being cleared.



I believe my issue relates to:
http://docs.handsontable.com/0.28.4/demo-custom-renderers.html
However I have followed the guidance:


You can also put HTML into row and column headers. If you need to
attach events to DOM elements like the checkbox below, just remember
to identify the element by class name, not by id. This is because row
and column headers are duplicated in the DOM tree and id attribute
must be unique.


I have been referencing the search boxes by class as suggested and I have adjusted my code to expect multiple occurrences of the search boxes.



$(document).ready(function () {
var colHeaders = [
'ID</br><input name="id" type="text" class="searchID" size="1">',
'Name</br><input name="name" type="text" class="searchName" size="20">',
'Address</br><input name="address" type="text" class="searchAddress" size="10">'
];
var data = [
{id: 1, name: 'Ted Right', address: 'A'},
{id: 2, name: 'Frank Honest', address: 'B'},
{id: 3, name: 'Joan Well', address: 'C'},
{id: 4, name: 'Gail Polite', address: 'D'},
{id: 5, name: 'Michael Fair', address: 'E'},
{id: 6, name: 'Ted Right2', address: 'A'},
{id: 7, name: 'Frank Honest2', address: 'B'},
{id: 8, name: 'Joan Well2', address: 'C'},
{id: 9, name: 'Gail Polite2', address: 'D'},
{id: 10, name: 'Michael Fair2', address: 'E'},
{id: 11, name: 'Ted Right3', address: 'A'},
{id: 12, name: 'Frank Honest3', address: 'B'},
{id: 13, name: 'Joan Well3', address: 'C'},
{id: 14, name: 'Gail Polite3', address: 'D'},
{id: 15, name: 'Michael Fair3', address: 'E'},
{id: 16, name: 'Ted Right4', address: 'A'},
{id: 17, name: 'Frank Honest4', address: 'B'},
{id: 18, name: 'Joan Well4', address: 'C'},
{id: 19, name: 'Gail Polite4', address: 'D'},
{id: 20, name: 'Michael Fair4', address: 'E'},
{id: 21, name: 'Ted Right3', address: 'A'},
{id: 22, name: 'Frank Honest3', address: 'B'},
{id: 23, name: 'Joan Well3', address: 'C'},
{id: 24, name: 'Gail Polite3', address: 'D'},
{id: 25, name: 'Michael Fair3', address: 'E'},
{id: 26, name: 'Ted Right4', address: 'A'},
{id: 27, name: 'Frank Honest4', address: 'B'},
{id: 28, name: 'Joan Well4', address: 'C'},
{id: 29, name: 'Gail Polite4', address: 'D'},
{id: 30, name: 'Michael Fair4', address: 'E'},
];
var $container = $("#HoT");
var searchParams = '';
var searchObj = {};
searchObj[0] = {key: 'searchID', className: '.searchID', saved: null};
searchObj[1] = {key: 'searchName', className: '.searchName', saved: null};
searchObj[2] = {key: 'searchAddress', className: '.searchAddress', saved: null};

$container.handsontable({
data: data,
colHeaders: colHeaders,
contextMenu: false,
});

//loadSavedSearchTerms();
searchHandlers();

function searchHandlers(){
for(i=0; i < 3; ++i){
$(document).on('keydown', searchObj[i].className, function(e){
if(e.which === 13) { // Return Pressed
fetchSearchParams();
}
});
}
}
/*
function loadSavedSearchTerms(){
for(i=0; i < 3; ++i){
if(searchObj[i].saved){ // If a search component previously stored
$(searchObj[i].className).each(function(j, obj){
obj.value = searchObj[i].saved;
});
}
}
}
*/
function fetchSearchParams(){
searchParams = '';
// Fetch values from all input fields
// Note immensely more complicated due to HoT beaviour causing duplications in DOM
for(i=0; i < 3; ++i){
//Due to duplication by HoT return array of values for each input
searchObj[i].arrayHoT = $(searchObj[i].className).map(function() {
return this.value;
}).get();

//Save any terms for this input for future use e.g. sort/scroll ajax call (not included here)
if(searchObj[i].arrayHoT[0])
searchObj[i].saved = searchObj[i].arrayHoT[0];
else if(searchObj[i].arrayHoT[1])
searchObj[i].saved = searchObj[i].arrayHoT[1];

if(searchObj[i].saved){
searchParams += '&'+searchObj[i].key+'='+searchObj[i].saved;
}
}
console.log('Final Search params: '+searchParams);
// Filter Data - AJAX Call with params
//return getData(searchParams).done(loadHOT);
}
});

</style><!-- Ugly Hack due to jsFiddle issue --> <script src="http://docs.handsontable.com/scripts/jquery.min.js"></script> <script src="http://docs.handsontable.com/bower_components/handsontable/dist/handsontable.full.js"></script> <link type="text/css" rel="stylesheet" href="http://docs.handsontable.com//bower_components/handsontable/dist/handsontable.full.min.css"> <link rel="stylesheet" media="screen" href="http://handsontable.com/demo/css/samples.css">

<h2>Search Values - Maintain on scroll</h2>
<div id="HoT" class="handsontable"></div>





Any suggestions/ideas on how to maintain the search values entered?

Note: I have since submitted this as an issue:
HoT Issue - Frozen Header, Input Element Data is Lost on Scroll

Answer

The issue I describe has been confirmed as a bug.

From AMBudnik at handsontable:

When we add renderAllRows: true the issue stops so I guess that this has something to do with the viewport.

Please see Handsontable Github for any updates