How can you specify the row id or class with a specific id?
<tr id="row1">
Or even this is ok
<tr class="row1">
I was thinking something like this would work but it doesn't.
#grid.GetHtml(
rowStyle: "row_" + grid.Column(columnName: "Id")
Anyone have any idea how i can possibly use the htmlAttributes or something to get this?
If i was using the for loop then thats easy but the WebGrid allows me to sort and page.
#foreach (var item in Model)
{
var rowid = "row" + #item.Id;
<tr id="#rowid">
checkout this post: http://haacked.com/archive/2011/04/14/a-better-razor-foreach-loop.aspx
eventhough the demonstration is done using FOREACH loop it is very easy to imagine this solution with regular grid control "bound" to model. the thing is that you will calculate this ID as the very last operation before you send the model to view so it works also for sorted grid (so first row has ID = 1).
btw. i really dont get it why this is not supported by grid directly. it is problem also in MVC Contrib grid (ok, this is OSS project so instead of bitching i should implement it :) ). i found such IDs inevitable when you want to make the grid editable because of the way ASP.NET MVC 3 model binder works.
Related
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);
}
});
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.
When invoking destroy() in KendoUI Grid and then recreate the table on a new DataSource: why do the old table columns still exist?
The only element here that stays the say is the element. How do I tell the grid to read the new datasource columns (it reads everything else correct).
(if I make 2 different elements, they both populate properly but I rather just keep 1 element and replace the elements table by destroy and reinit)
Most probably this is because you are not clearing the content inside the Grid container. e.g.
$('#gridName').data().kendoGrid.destroy();
$('#gridName').empty();
or shorter syntax
$('#gridName').kendoGrid('destroy').empty();
Other way the Grid takes into account the old html that is left - do not forget that the Grid could be initialized from table like here.
Just want to clarify on the last bit of Peter Subev's answer because it helped me:
"do not forget that the Grid could be initialized from table like here"
This is just saying that in your HTML you used a <table> tag rather than a <div> tag. Using a <table> tag separates the Grid table data from the Grid columns, so when you do $('#gridName').kendoGrid('destroy').empty() it is only destroying/emptying the table data and not the column information.
Switch your HTML <table> tag to a <div> tag to get the desired result.
I'm working in the angular framework and can't seem to reinit the Kendo grid with a new dataSource and new columns. Nothing works on the 2nd grid init. I've tried:
if (vm.mainHierGrid != null) {
//vm.mainHierGrid.data().kendoGrid.destroy();
$('#mainGrid').data().kendoGrid.destroy();
//$('#mainGrid').empty();
vm.mainHierGrid.destroy();
}
Destroy kendo grid and rebind it
if ($('#kgCopyEntityGrid').hasClass("k-grid")) {
$('#kgCopyEntityGrid').kendoGrid('destroy').empty();
}
var kgCopyGrid = $("#kgCopyEntityGrid").kendoGrid({
// your code here
}).data("kendoGrid");
I am using a WebGrid to display a list of items,
I like to set the background color of the rows based on a condition. I want to set the background color of the entire row, not just one cell.
Any example?
thank you
This is an old question, but I just stumbled upon it and have an answer that I don't think is too hacky. The previous answer supplied only works if the value you're using to conditionally change the background color is the value of a table cell.
If that's not the case, you can set a data- attribute for the first cell in your table rows using the Format property of a WebGridColumn. Here, the first column of my table contains hyperlinked IDs. I'm defining it in my code-behind (controller action in MVC) and I've added a data-in-error attribute from the IsInError property of my object. You can set the value of this attribute in whatever way makes sense for your application.
new WebGridColumn
{
ColumnName = "Id",
Header = "ID",
Format = (x) => new HtmlString(String.Format("{1}", x.Value.IsInError, x.Value.Id))
});
Then, using jQuery, I find all of the rows in my table that have an anchor in the first cell of the row, and set the class of that row to 'error'.
$(document).ready(function () {
$('table tbody tr td:first-child a[data-in-error="True"]').each(function () {
$(this).parent().parent().addClass('error');
});
});
Hope this helps.
Is jQuery an option? If so, check out: http://devpinoy.org/blogs/keithrull/archive/2010/06/09/how-to-change-table-cell-color-depending-on-its-value-using-jquery.aspx
On my page I have two webGrids. When I click on one to sort that column, both of the grids are sorted on that column. Sorting on a column that is only in one, doesn't sort at all.
I noticed the sorting works by making the header a link to the same page with in the query string a column and a direction. This explains that both grids are affected. I was wondering if the webGrid has some functionality to solve my problem or should I fix it myself.
The way I am planning to "fix it myself" is to first add an id attributes to the table tags by setting the htmlAttributes. Then I will use jQuery to find this id for every webgrid and incorporate that id in the links parameters. Then when loading a page with a grid I will forcably set which column to sort on based on those parameters.
It seems to me the webGrid is not designed to be on a page with another webGrid. However, I feel that in my situation it is desired. I prefer to use some standard way (built in or just what everyone else uses).
So the question is, what is the best way to do it? And if there is no best way, is my way a good way (did I forget about something)?
Thanks in advance.
I think you need to set the following properties:
string fieldNamePrefix = null
//The value which prefixes the default querystring fields
string pageFieldName = null
//A value that replaces the default querystring page field
var grid1 = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid1", fieldNamePrefix:"g1",pageFieldName: "p1");
var grid2 = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid2", fieldNamePrefix:"g2",pageFieldName: "p2");