I have some javascript that changes the content of certain cells in a handsontable grid.
The issue I have found is that when I change the content of one of the cells the frozen column rows don't change accordingly.
Is there a function that can be run to check the sizes of each row and resize accordingly?
I have a Jsfiddle which shows the issue:
http://jsfiddle.net/JammyDodger231/145bL7ej/
var myData = Handsontable.helper.createSpreadsheetData(4, 20);
hot = new Handsontable(container, {
data: myData,
rowHeaders: true,
colHeaders: true,
fixedRowsTop: 2,
fixedColumnsLeft: 2
});
//Hardcoded just to show issue, this isnt where the content would be changed
$('.htCore tbody tr:nth-child(2) td:nth-child(5)').html("Test <br /><br />");
Your problem is that you should NEVER manually change content or CSS on the table that Handsontable renders for you. It is a stateless table which will get overriden as soon as you make any changes that triggers a change event. Read this answer to get a more detailed description:
CSS applied on Handsontable grid row on Scroll is not working properly
What you should be doing instead is using the methods that Handsontable supplies to you. In your case, you can use hot.setDataAtCell(row, col, value). You could also directly change myData since Handson uses a reference to it. Anything but manually changing the DOM.
Related
How to tell to jQuery tabledit that the rows are changed? The buttons only generated for existing rows, when I add a new row (for example using jQuery), the table buttons doesn’t appear in the new row. I saw in tabledit code, that there is possibility to switch between view and edit mode (maybe this would help me), but don’t know how to access these methods after the tabledit is created and when rows has been changed.
A little snippet from my code:
$(document).ready(function(){
$(‘#btn’).click(function(){ ... adding row, I need to update tabledit here });
$(‘#table’).Tabledit(...parameters...); }
});
tabledit
Here is the best solution I could come up with for your situation.
I created an "Add" button. NOTE the for-table attribute so I can figure out what table to add to later.
<button id='add' for-table='#example1'>Add Row</button>
Then I created a click handler for the "Add" button.
$("#add").click(function(e){
var table = $(this).attr('for-table'); //get the target table selector
var $tr = $(table + ">tbody>tr:last-child").clone(true, true); //clone the last row
var nextID = parseInt($tr.find("input.tabledit-identifier").val()) + 1; //get the ID and add one.
$tr.find("input.tabledit-identifier").val(nextID); //set the row identifier
$tr.find("span.tabledit-identifier").text(nextID); //set the row identifier
$(table + ">tbody").append($tr); //add the row to the table
$tr.find(".tabledit-edit-button").click(); //pretend to click the edit button
$tr.find("input:not([type=hidden]), select").val(""); //wipe out the inputs.
});
Essentially;
Deep Clone the last row of the table. (copies the data and attached events)
Determine and set the row identifier.
Append the new row.
Automatically click the Edit button.
Clear all inputs and selects.
In my limited testing this technique appears to work.
jQuery Tabledit should be executed every time a table is reloaded. See answer given here:
refreshing Tabledit after pagination
This means that every time you reload the table (e.g. navigating to new page, refreshing etc), you must initialize Tabledit on the page of the table where it wasn't initialized. The problem is that there is no way to know whether Tabledit has been initialized on the table already, hence if you re-initialize it, duplicate buttons (edit, delete..) will be added to the rows of the table. You also cannot destroy a non-existent Tabledit, hence calling 'destroy' always beforehand will not help.
I hence created my own function to tell me if Tabledit is initialized on a certain page of a table or not:
function hasTabledit($table) {
return $('tbody tr:first td:last > div', $table).hasClass("tabledit-toolbar");
}
and using it as follows:
if( !hasTabledit($('#table')) ) {
$('#table').Tabledit({
url: 'example.php',
columns: {
identifier: [0, 'id'],
editable: [[1, 'points'], [2, 'notes']]
},
editButton: true,
deleteButton: false
});
}
The hasTabledit(..) function checks whether the last cell of the first row of the table has a div which has the tabledit-toolbar class, since this is the div that holds the Tabledit buttons. You may improve it as you like. This is not the perfect solution but it is the best I could do.
I have a grid with handsontable but this grid is wider than the screen. Here is a capture of what it looks like :
As you can see, I have a scroll bar because the grid is too wide.
The user insert some data in this grid and I make a request in ajax to test the content (required field, numeric field, ...) When there is an error, I return a number to know which cell is incorrect. I use this number like that :
$(cells).eq(jsonobject[item]-11).css("background-color","red");
With the .eq function I can select the cell I want. But when the grid is wider than the screen, I feel that the index of each cell is moved.
Here is a wonderful sketch of what I think :
So the indexes are dependants of the screen but not of the grid.
How can I overcome this problem please ?
EDIT :
The code where I declare my hot :
var container = document.getElementById('tab_traitement');
var hotTraitement = new Handsontable(container, {
data: data_traitement,
stretchH: 'all',
minSpareRows: 1,
observeChanges : true,
rowHeaders: false,
colHeaders: false,
contextMenu: true,
height: 550,
... //more options
In the ajax return, I get an array of values with some indexes where the data is incorrect and I try to color the cell in question. So I tried like that :
for(var i=1; i<(data_traitement[0].length);i++ )
{
for(var item in jsonobject)
{
if((item % 2 ) == 0) //Si l'indice est pair, on affiche la couleur
{
hotTraitement.getCell(i,jsonobject[item]-j).css("background-color","red"); //Here, firebug tells me "hotTraitement is undefined"
}else
{
$(cells).eq(jsonobject[item-1]-1).qtip({
content : '<div id="bulle">'+jsonobject[item]+'</div>',
position: {
adjust: {
x: -100
}
},
style: {
classes: 'myCustomClass',
def: false
}
});
}
}
j = j+3; //Just to loop through the rows (I have 3 cells in a row)
}
Well to start off, there's virtual rendering happening horizontally meaning that if you were to have a table with many many columns, most aren't being rendered therefore jquery will never find them.
Now, to do this more efficiently, I would simply get the cell using the HOT methods included:
hot.getCell(row,col);
This returns to you the TD after which you could attempt to do the css like you were asking.
I don't think this would be the best way to go, however, because physically modifying the DOM doesn't work well with Handson given that it re-renders pretty frequently. Instead, you should be setting the custom renderers on each cell to respond to your validation efforts. A simplistic solution is to have an array with cell coordinates which should be marked as "invalid". The custom renderer could then ask if the current cell coordinates are in this array and if so, apply your css logic as you did above.
And just FYI, Handson has wonderful validation functionality built in which I highly recommend using. It will apply a class name for you if it fails validation so there wouldn't even be a need to do any fancy cell finding, just add the class you want and in your CSS file attach whatever style you want.
I've tried with no success to implement x-editable in bootstrap datatables, the reason being when i update an element from x editable, the datatable fails to recognize those changes.. i've tried updating the table, destroying it, hidden tags, but the main problem seems to be that the datatables fails to recognize any change after the initialization..
I add the rows via button click, when they get to the table, i run .editable on those elements. they become editable but the sorting and search of the datatables doesnt work..
Can anyone help me?
The problem is that for performance reasons, Datatables caches the table into memory so actually the DOM table is different from the in-memory table. And when you modify the DOM, it doesn't change the table in-memory.
Therefore, Datatables created a function helper : invalidate() that you can apply on a row http://datatables.net/reference/api/row%28%29.invalidate%28%29 (there is a multiple rows version too).
Or you can still use the function data() which is less CPU consuming (recommended).
I would do something like this :
$('.xeditable').on('save', function(e, params) {
var $tr = $(e.target).closest('tr');
var newValue = params.newValue;
//If you didn't save the datatable into a var table, you need to call this line :
//var table = $('#example').DataTable();
table.row(tr).data(newValue);
//Or table.row(tr).invalidate(); which should read from the DOM directly
});
I have a problem with a jqGrid table that i'm unable to find a solution nor an answer that guides me in the correct direction, i've read some answers in SO but none of them focuses on my problem:
JQGrid data not being displayed
jqgrid fail to display json data
jqGrid fetched json but has empty rows and no data
JqGrid is not able to display data
JQGrid not showing json data
Many of the related questions that i've read so far focuses on populating the grid with JSON data, but that's not my case. The way i fill the grid is with the addRowData method, and it seems to work, because when i inspect the table element on the debug tools of the browser (Chrome 29.0.1547.76 m) and the table, tbody plus all the tr elements exists with the expected data, but they aren't visible!
inspection screenshot
All the rows have the width and height with 0px value, that's why (i suppose) the data doesn't show. But i use the same method to display another tables and the result is visible.
I cannot paste all the code because is messy and spagetty, but i'll try to provide useful information:
// The ConvertTojqGrid method converts the data (array object)
// into the format expected by jqGrid in order to provide the
// colModel and rows
var jqGridData = ConvertTojqGrid(data);
// the divID begins with '#'
var div = jQuery(divID)[0];
var table = divID + '_table'
jQuery(divID).append('<table id="' + table.substr(1) + '"></table>');
// get rid of the '#' in the string ^^^^^^^^^^^^^^^
jQuery(table).jqGrid(
{
autowidth: true,
gridview: true,
headertitles: true,
datatype: 'clientSide',
caption: gridCaption,
colModel: jqGridData.colModel,
records: jqGridData.rows.length,
height: div.clientHeight,
width: div.clientWidth
});
jqGridData.rows.forEach(function(row)
{
jQuery(table).addRowData('row_id', row);
});
The webpage shows a table with data that is displayed as expected but with some columns hidden, on top left of the table a button is placed, this button shows a form with another grid that displays the same table without hidden columns.
All the tables are placed into a runtime-generated div and into this div a table tag is generated in order to contain the grid.
In brief, the problem isn't in obtaining the data nor in filling the table, the problem is that the data is correct and the table is filled but the rows aren't visible.
Any advice will be wellcome.
Try in your jqGrid definition setting datatype: "local".
If that doesn't work, what does your colModel look like, and do you have a sample of the data format you're using to populate a row?
I have two distinct gridpanels and throughout my code, whenever value of one of the cells in Grid1 changes I want to be able to change value of certain cells in the Grid2,
How can I change the css of the second grid from within the Grid1.
The following allows me to change the css for an entire row in Grid2 but I need to be able to change the css for a cell of Grid2 row: 2, column 3
var Grid2Store= Ext.data.StoreManager.get("MainComparisonStore");
Grid2.getView().addRowCls(Grid2Store.getAt(2), 'orange-bar');
Get a hold of the element and you can use cellElement.addCls('orange-bar');. See Ext.dom.Element.addCls() documentation. I put together a jsFiddle for you to see an example. Just click the "Test" button in the grid toolbar.
Here is the code that does the work. It is hard coded to add a class to column 1, row 1.
var grid = Ext.getCmp('myGrid');
var column = grid.columns[1];
var record = grid.store.getAt(1);
var cell = grid.getView().getCell(record, column);
cell.addCls('orange-bar');
Here (Sencha Forum) is some discussion on how to get the cell. This is what I used to put together my example. You can see how you could make a helper like getCell(rowIndex, columnIndex) pretty easily.