How to select a row in kendo grid by data item ID? - kendo-ui

I need to select a specific row in kendoGrid but NOT by data-uid (as data-uid is changed when the grid dataSource is loaded again) but by the row itemID. I saw posts but they only select the row by uid which is not what I needed, I actually need to restart the HTML5 application and when grid is loaded, a specific item should be selected. This is what I've been seeing
Demo: jsfiddle.net/rusev/qvKRk/3/
e.g. the object has OrderID as ID, and every time the grid is loaded, it will be the same, unlike uid, I want to know how will I be able to select a row with OrderID, instead of uid.

You cam mix row itemID and data.uid, I guess.
var grid = $("#Grid").data("kendoGrid");
var dataItem = $("#Grid").data("kendoGrid").dataSource.get(itemID);
var row = $("#Grid").data("kendoGrid").tbody.find("tr[data-uid='" + dataItem.uid + "']");

Going along with what umais has mentioned, the better approach, since there is no built in functionality for this as of yet, would be to iterate through all the records to find the one you need. The function that I built will work even if there are pages of data. The only other way that I can think of doing this would be do do a secondary ajax call; But this works well. Note that i haven't tested it with more than 2000 records.
var dataGrid = $("#GATIPS").data("kendoGrid").dataSource;
var numOfRows = dataGrid.total();
var currentPageSize = dataGrid.pageSize();
dataGrid.pageSize(numOfRows);
var dataGridData = dataGrid.data();
for (var i = 0; i < numOfRows; i++) {
if (dataGridData[i].uid == e)
return dataGridData[i];
}
dataGrid.pageSize(currentPageSize); // reset the view
e is the UID. However this can be substituted for what ever variable you need just replace the check.

a work around that I managed to have, was to go through all rows and check which row model has that ID equal to the parameter, and then get that row data-uid and select the item through data-uid. It's working fine for me, since there were no suggestion, it's the better answer for now.

Well, accordingly to what I have done (and worked for me), and even though the work around isn't the prettiest, set one more Column, with your model id and with ClientTemplate then create any html object (div in my case) inside it give it a html id of your id, so when ever you need it, you just have to go and look with something like:
grid.dataItem($("td div#id").closest("tr"));
Because remember that the dataItem method is waiting for a selector then you get your selectedItem as regular one.
EDIT:
I forgot to say, that you should (or could) use the style property
display:none
If you don't want to display that col.

Related

Extra row atop Kendo Treelist

We have a Kendo TreeList that works fine. Data shows, everything shows in the hierarchy correctly. The problem is, we need to group each two columns into another "superset" group.
The column headings (the names above are not real) are too long if not grouped as shown, and they lose useful context.
I tried adding an HTML table above the TreeList, but that doesn't look right. And it doesn't work if the user resizes the columns. Also the toolbar (for Excel export) is in the way, so it doesn't even look like it's part of the TreeList.
I also looked at wrapping the text in the columns, but from what I've seen, that's really iffy too.
It seems like an extra row as shown above (with the ability to merge some columns, like with an HTML table) is the best way to go. Despite scouring the web, I couldn't find a way to do this. Is this even possible with a Kendo TreeList?
This has been solved. Not by me, but by another developer on our team who's insanely good at JavaScript.
The trick is to edit the TreeList's HTML and CSS through JavaScript. You can bind to any event, but we do it on page load:
<script>
$(document).ready(function () {
// anything in here will get executed when the page is loaded
addTopRowToTreeList();
});
function addTopRowToTreeList() {
// grab the thead section
// your HTML may be different
var foo = $('#MyTreeList').children('div.k-grid-header').children('div.k-grid-header-wrap');
var tableChild = foo.children('table');
var headChild = tableChild.children('thead');
var bottomRow = headChild.children('tr');
var topRow = $('<tr>').attr('role', 'row');
// bottom cell should draw a border on the left
bottomRow.children('th').eq(0).addClass('k-first');
// add blank cell
var myNewCell = $('<th>').addClass('k-header').attr('colspan', '1')
var headerString = '';
var headerText = $('<span>').addClass('k-link').text(headerString);
myNewCell.append(headerText);
topRow.append(myNewCell);
// ... add remaining cells, like above
headChild.prepend(topRow);
}
</script>
That's all there is to it!

jqGrid: update a row AND have its formatters updated as well

Ideally I would call setRowData and have my cell formatters and rowattr function re-run, but cell formatters and rowattr functions don't re-run when calling setRowData (I don't know why but that's another question maybe), so setRowData isn't really helpful for me.
It seems the next easiest thing to do would be to remove a row and re-add a new one at the same position with the same model. To do that I need to get the rowid of the row above the selected row so that I can call addRowData and specify the ID of the row above in srcrowid and use 'after' for the position. This is what I'm thinking:
$.jgrid.extend({
updateRow: function(rowid, model){
// get index from id
var index = this.jqGrid('getInd', rowid);
// note: my first row's index is 1 (is that normal?)
if ( index == 1 ){
position = 'first';
srcrowid = 'n/a';
}
else{
position = 'after';
srcrowid = _____ how to get rowid of row above selected row _____???
}
// delete row
this.jqGrid('delRowData', rowid);
// insert at index
this.jqGrid('addRowData', rowid, model.attributes, position, srcrowid);
}
});
How can I get the rowid of the row above the selected row? (Is there an easier way? Is this a bad strategy?)
Note: I'm using backbone.js collections and models
I find the best way to change the row is to use setRowData instead of usage delRowData and addRowData. If you know rowid then you can use $("#" + rowid); (or if rowis have special characters like :, . an so on then $("#" + $.jgrid.jqID(rowid));) to get the <tr> element. Then you can use jQuery.addClass, jQuery.css, jQuery.attr to change the attributes of the row.
It's important to understand that jqGrid uses the same methods internally it it's required to modify element of the grid. The main goal of rowattr is another one. During filling of the grid data there are many scenarios. One can create DOM elements for <td> and <td> and insert there in the grid. The main problem is performance in case of working with DOM. It's much slowly as building of strings. Moreover DOM is even much more slowly if the elements are exist on the the HTML page (in opposite to disconnected elements). If one modify one element only from the grid having 500 rows then the position of elements of all other rows need be recalculated.
Because of the problem jqGrid construct the whole body of the grid first in string format and then assign all <tr> and <td> elements using one set of innerHTML. It improves dramatically the performance of filling of the grid. See the answer for additional information. The formatters and callbacks cellattr and rowattr are introduced to allow to customize cell and row attributes during building of grid body in string format. It gives you customization possibilities without reducing of performance.
On the other side if you need to modify the row which are attached already on HTML page then you will have no advantage with working with strings instead of DOM. Because of that I recommend you just use jQuery.addClass, jQuery.css, jQuery.attr directly. If you need to change multiple classes, assign multiple css rules or multiple attributes then you should use one call of above functions. You can use object form of jQuery.css, jQuery.attr for it.
The updateRow extension below works, BUT I ended up not using it. Not so much for the reasons Oleg talked about (which I assume are valid and something you should definitely consider), but because I had a filter provider that was too difficult to sync with (e.g. after soft deleting a row, I need to now determine if new deleted status agrees with current filter...and that's a pretty simple example). So I just defer to the data the filter provider gives me and repopulate the grid each time, which I'm not fond of, but I don't see other easy options.
As far as the extension below goes, here are pros/cons as I see them:
Pros:
easy to use
You just rely on the rowattr functions and cell formatters you already defined. You don't have to write those twice.
Cons:
possibly performance--see Oleg's answer
please add any you see
Unknowns:
performance? I have no idea how much worse it performs. It would be interesting to do benchmarks with different browsers. I saw no problems, but I only have maybe 20 rows. Let's say we're working with 500 rows and adding/removing classes and calling .css() took 30 ms but using the extension took 300 ms on a 'typical' machine/browser. That would be 10 times slower, but for me it would probably be worth it because I don't have to write something twice.
here's the extension:
$.jgrid.extend({
updateRow: function(rowid, data){
// get index from id
var index = this.jqGrid('getInd', rowid);
// note: my first row's index is 1 (is that normal?)
if ( index == 1 ){
position = 'first';
}
else{
position = 'after';
srcrowid = $(this).find('tr#' + rowid).prev()[0].id;
}
// delete row
this.jqGrid('delRowData', rowid);
// insert at index
this.jqGrid('addRowData', rowid, data, position, srcrowid);
}
});

Hiding columns of handsontable from javascript

Is there any way i can hide HOT columns from javascript?
The requirement is such that the column to hide will come as a parameter in javascript and based on that the respective column will show hide accordingly.
The HOT has rowHeaders and colHeaders and the data with 20 columns.
Please advise.
OUTDATED SOLUTION
Ok I founnd a possible solution. I tested it out on my own system but it's actually quite simple.
You should be using a customRenderer in your columns option. Read up about this if you aren't already. The idea is that you're giving each cell its own renderer. In this custom function, you can do something like this:
var colsToHide = [3,4,6]; // hide the fourth, fifth, and seventh columns
function getCustomRenderer() {
return function(instance, td, row, col, prop, value, cellProperties) {
if (colsToHide.indexOf(col) > -1) {
td.hidden = true;
} else {
td.hidden = false;
}
}
}
What this renderer does is hide the cells that the var colsToHide specify. All you do now is add a DOM element that lets the user pick which and so every time the table gets rendered (which happens basically after any change, or manually triggered need be), the cells in the columns specified will be hidden, keeping the data array intact like you described. And when not in colsToHide they are re-rendered so make sure you get that working as well.
Here I implemented it with very basic functionality. Just enter the index of a column into the input fields and watch the magic happen.
http://jsfiddle.net/zekedroid/LkLkd405/2/
Better Solution: handsontable: hide some columns without changing data array/object

Programatically updating underlying data in Slickgrid

I have 6 textboxes at the top of the screen that update an entire column(one textbox per column) based on any changes. I was selecting the columns based on their class (.l#). Here is the code (issues to follow):
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = [".l1", ".l7", ".l8", ".l9"];
var fields = $(bound[id]);
for (var i = 0; i < fields.length; i++)
{
fields[i].innerHTML = $(ctrl).val();
}
};
which is bound to the keyup event for the text areas. Issues are:
1) initially fields.length was -1 as I didn't want to put data in the "add new
row" section at the bottom. However, when running it, I noticed the
final "real" record wasn't being populated. Also, when stepping through, I
noticed that the "new row" field was before the "last row" field.
2) when doing it this way, it is purely superficial: if I double click the field,
the real data hasn't been changed.
so in the grand scheme of things, I know that I was doing it wrong. I'm assuming it involves updating the data and then forcing a render, but I'm not certain.
Figured out how to do it. Modified the original code this way:
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = ['title1', 'title2', 'title3', 'title4'];
var field = bound[id];
for (var i = 0; i < dataView.getLength(); i++)
{
var item = dataView.getItem(i);
item[field] = $(ctrl).val();
dataView.updateItem(i, item);
}
grid.invalidate();
};
I have 6 textboxes (item1-item6) that "bind" to fields in the sense that if I change data in a textbox, it updates all of the rows and any new rows added also have this data.
Parts where the two issues can be explained this way:
1) to work around that, though still it would be a presentational fix and not a real updating of the underlying data, one could force it to ignore if it had the active class attached. Extra work, and not in the "real" direction one is going for (masking the field).
2) It was pretty obvious with the original implementation (though it was all I could figure out via Chrome Dev Tools that I could modify at the time) that it was merely updating a div's content and not actually interacting with the data underneath. Would look nice, and perhaps one could just pull data from the item1-item6 boxes in place of the column if it is submitted, but if someone attempts to modify the cell, they'll be looking at the real data again.

JQgrid : specific value from a selected row

how to get a value of a (hidden) column, from the selected row. that is, the cell value needs to be from the cell identied by colName, and the selected row (not using multi select). From the API i see the method getGridParam("selrow") for reading the row, may be able to combine with other methods.. but, any convenient method available? a code snippet would save lot of time... \
thanks.
You should use getCell function to read the value from the cell identified by row id. So if you need a data from the column 'MyColName' of selected row you can do this with the following code:
var grid = jQuery('#list');
var sel_id = grid.jqGrid('getGridParam', 'selrow');
var myCellData = grid.jqGrid('getCell', sel_id, 'MyColName');
If you need read full data of a row you can use getRowData instead of getCell. More about methods supported by jqGrid you can read in the documentation (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:methods).

Resources