Super noob question here. I have an array of row indexes that I would like to use to change the color of my Handsontable rows. I figure HOT would provide a method to retrieve the tr element of a table with something like hot.getRow(5), but it doesn't seem to exist.
So in a nutshell I'm trying to do this
var rowIds = []
$.each(rowIds , function (i, element) {
var row = hot.getRow(i);
$(row).closest('tr').css('color','green');
});
I've found I can use getCell() method which accepts a row and column # along with a boolean, but using this would require extra code for something that should be as simple as passing a single argument. Is there a method I'm overlooking or is this the only way?
Here's the thing with how HOT works: it is a JS object which renders a stateless DOM table. This means you should never EVER try to manually modify the HTML of your table. Even if you did want to do that, as soon as you make a change to those green cells, they would get re-rendered, not green.
Instead, you want to use the readily accessible 'custom renderers' that are associated with each column or cell, depending on how you define them. These are applied just like the data attribute in the columns or cells definition. They are functions and here's an example:
function greenCellRenderer(instance, td, row, col, prop, value, cellProperties) {
Handsontable.renderers.TextRenderer.apply(this, arguments);
td.style.color = 'green';
}
You should read up on the full documentation to understand the full power of the renderer but it's pretty clear from the arguments it takes what you can do. One thing you would be able to do is apply the green color you're hoping for. Of course to selectively do this you would either apply the renderer to specific cells, or put a conditional inside this general renderer using the row and col arguments to your advantage.
Hope that helps!
Related
I would like to use Ag Data Grid filtered data to generate plots in Vega-Lite that update automatically whenever the filter(s) are changed. I would prefer to have the implementation in an observablehq notebook. Here is a section on how to access the table data in Ag Grid documentation. I created an observablehq notebook where the chart is updated using a button. There are two issues with this implementation:
The chart is generated only after the button is clicked.
I would prefer the chart update to be automatic without the need to click a button.
Thanks for linking to the notebook! It appears that the angular table does update, but it appends to the element and gets drawn behind the code cells. This is what it looks like in my browser when I move the slider:
The problem with components like this that manipulate the DOM is that they work against Observable's way of managing the DOM. Even if the component were to update correctly, it would probably still not resize the way you'd expect.
Observable is already reactive at its core, which is something angular (and other frameworks like React) was built to add to JavaScript. Using Observable's built-in reactivity will be much easier in the long run than trying to make two different reactivity models work with each other.
You can make the AG Grid table an Observable “view” so that you can both (1) see the table and (2) refer to its value in other cells, which will re-run when you filter the table. Once you do that, it'll work naturally with anything else you want to do in the notebook. Here's a working example with Observable Plot, and here's the same example with Vega-Lite.
Assuming you've loaded AgGrid and have gridOptions in a different cell, you can wrap AgGrid as an Observable view like this:
viewof table = {
const node = htl.html`<div style="height:320px;" class="ag-theme-alpine"></div>`;
new AgGrid.Grid(node, gridOptions);
gridOptions.api.addEventListener("modelUpdated", update) // set value after filter
gridOptions.api.sizeColumnsToFit();
update(); // set initial value
function update() { // for Observable dataflow
let value = [];
gridOptions.api.forEachNodeAfterFilter(d => value.push(d.data));
node.value = value;
node.dispatchEvent(new Event("input"));
}
return node;
}
A few notes on how this is different from your version (as of when I saw it):
I put the HTML and the AgGrid initialization in the same cell, so that AgGrid has an object reference to the node and if you re-run the cell it all gets cleaned up and recreated as a whole.
I listen for when the grid rows change with gridOptions.api.addEventListener("modelUpdated", update).
In that update function, I do the same iteration over the rows that you were doing to build an array, but then I set it as the value of the node, and dispatch an input event from that node. That's what Observable looks for to tell when a view has changed its value and other cells should re-run.
I name the cell viewof table. You might've seen this pattern with sliders and other inputs on Observable. The viewof keyword means that you get the DOM node rendered, but you can also refer to its value with just table in other cells.
Thanks for the question; I’ve been meaning to check out AG Grid for a while!
I am using tabulator package 4.3.0 to work on a webpage. The table generated by the package is going to be the control element of a few other plots. In order to achieve this, I have been adding a dataFiltered function when defining the table variable. But instead of getting the order of the rows in my data object, I want to figure a way to get the index of the rows in the filtered table.
Currently, I searched the manual a little bit and have written the code analogue to this:
dataFiltered: function(filters,rows){
console.log(rows[0]._row.data)
console.log(rows[0].getPosition(true));
}
But the getPosition always returned -1, which refers to that the row is not found in the filtered table. I also generated a demo to show the real situ when running the function. with this link: https://jsfiddle.net/Binny92/3kbn8zet/53/.
I would really appreciate it if someone could help me explain a little bit of how could I get the real index of the row in the filtered data so that I could update the plot accordingly and why I am always getting -1 when running the code written in this way.
In addition, I wonder whether there is a way to retrieve the data also when the user is sorting the table. It's a pity that code using the following strategy is not working in the way I am expecting since it is not reacting to the sort action and will not show the information when loading the page for the first time.
$('#trialTable').on('change',function(x){console.log("Yes")})
Thank you for your help in advance.
The reason this is happening is because the dataFiltered callback is triggered after the rows are filtered but before they have been laid out on the table, so they wont necessarily be ready by the time you call the getPosition function on them.
You might do better to use the renderComplete callback, which will also handle the scenario when the table is sorted, which would change the row positions.
You could then use the getRows function passing in the value "active" as the first augment return only rows that have passed the filter:
renderComplete: function(){
var rows = table.getRows("active");
console.log(rows[0].getPosition(true));
}
On a side note i notice you are trying to access the _row property to access the row data. By convention underscore properties are considered private in JavaScript and should not be accessed as it can result in unstable system behaviour.
Tabulator has an extensive set of functions on the Row Component to allow you to access anything you need. In the case of accessing a rows data, there is the getData function
var data = row.getData();
as far as I understand there is only the callback dataFiltered, which is used for the whole table. It is triggered by all filters indifferently.
Is it possible to get a callback for a specific single header filter?
So that I can call a function as soon as a certain header filter becomes active?
I imagine it to be something like this:
{title:"Name", field:"name", headerFilter:true, headerdataFiltered:function()}
Is there possibly a workaround?
Thanks a lot!
(I would be especially grateful for non-jquery solutions)
Thanks also for this realy wonderful tool Tabulator.
Thanks for your kind words, it is always great to hear that Tabulator is appreciated.
The reason it is called when any filter is applied is because multiple filters can be applied at once, with Complex Filtering a complex and/or filter set can be applied so it would be hard to isolate down to specific columns in all cases.
The dataFiltered callback does get passed a list of all currently active filters so you can see if your affected column is in that:
var table = new Tabulator("#example-table", {
dataFiltering:function(filters){
//filters - array of filters currently applied
},
});
If you need to see if the column has just been filtered you can store a copy of the previous value of this object outside the callback and then compare the old and new values on the next call.
The other option would be to use a custom editor in the header filter then you could manually decide when the success function is called that initiates the filter and then reference an external function from there
I am using google.visualization.DataTable and I have two relevant columns, we'll call them colSmall and colLarge. If colSmall is larger than colLarge in any given row, then I would like to make that row's background color red.
The closest I've come is by using google.visualization.ColorFormat(). I am able to make a formatter and addRange, which I can use to hard-code a particular value so that if colSmall is over that value, it will be red (see below).
var formatter = new google.visualization.ColorFormat();
formatter.addRange('100', null, 'black', 'red'); // anything greater than 100 will be red (the quotes are because these are string values)
formatter.format(data, 7); // colSmall is index 7
I have been unable to find a way to make it look at another column for this row. Another problem I have is that this only makes the cell red rather than the entire row.
I found a hacky way of doing it, but it I would still prefer something better.
Instead of building up the data and then adding it all to the table, I can insert each row into the table and format it there.
Then, for any given row, I can do something like:
var rowIndex = data.addRow(val);
if (colSmall > colLarge) {
data.setProperties(rowIndex, 2, {style: 'background-color:red'});
}
For each column in that row (rather than just column 2).
I would like to be able to use setProperty or, better yet, setRowProperty, but every time I try any of these methods, it simply does not work, so I'm settling for this for now.
I've a jqgrid and a getCell method which returns the value of a cell depending of id. It works only for the first row of the grid, in others identifyImg = false:
var ids = jQuery("#myGrid").getDataIDs();
for(var i=0;i<ids.length;i++){
var identifyImg = $('#myGrid').jqGrid('getCell', i, 'idState');
alert(identifyImg); // return false after first row
if(identifyImg == '1'){
//DO SOMETHING
}
}
the column is defined as the follow:
{name:'idState',index:'idState', width:55}
And is correctly populated with numbers. How can I solve this?
you should use
$('#myGrid').jqGrid('getCell', ids[i], 'idState');
instead of
$('#myGrid').jqGrid('getCell', i, 'idState');
I want additionally to mention that in the most cases one don't need use loop over ids returned from getDataIDs. It was a good approach in customizing of jqGrid inside of loadComplete or gridComplete in old versions of jqGrid. Now there are more better (from the performance point of view) alternatives. For example if you need to change some style or other attribute of one cell based on the content of one column you can use cellattr (see the answer, the answer, the answer, the answer or other). If you need to change some attributes of the whole row based on the content of one column you can use rowattr (see the answer). In other cases if you need to change content of the cell (not an attribute) based on the content of another cell you can use custom formatter.