SlickGrid CSS styles wrong on filtered view - slickgrid

I have a SlickGrid with dataview working pretty good, grid and dataview are synced up for modify and delete selections using syncGridSelection, however an interesting problem occurs on the changed CSS styles. The changed rows CSS stlye are being applied to the same "visible" row number in the grid when I choose a filter set that does not include the actual changed rows. The sort works fine, but I noticed that the filter is not working. Does anyone have a fix for this? Can you paste as much info and code for me as possible because I'm new to SlickGrid. I pasted code that loads up the grid.
function LoadGridData() {
$.getJSON('#Url.Action("GetConfigurations")', function (rows) {
if (rows.length > 0) {
if (rows[0].id = 'undefined') {
$(rows).each(function (index) {
rows[index].newAttribute = "id"
rows[index]["id"] = index;
});
}
};
data = rows;
dataView.beginUpdate();
dataView.setItems(data);
dataView.setFilter(filter);
dataView.endUpdate();
// Refresh the data render
grid.invalidate();
grid.render();
grid.setSelectedRows([]);
dataView.syncGridSelection(grid, true);
});
}

After debugging I found that I had used an older example of marking css changed in function getItemMetadata. The correct code is below. Previously I was referencing data[row]. When Syncing DataView to Grid, the getItem() method returns the correct row. In this case my DataState is my own changed indicator on the view model.
dataView.getItemMetadata = function (row) {
var item = this.getItem(row);
if (item && item.DataState == 2) {
return {
"cssClasses":
"changed"
};
}

Related

jqGrid Make a Row readonly

I have a grid setup using form editing. I want the the user to be able to edit only some of the rows. As a start, I figured the easiest way to do this was to have a column (probably hidden) in my server query and XML that denotes the Access or Role the user has. So essentially the grid now has a column "Access Role" with 'Y' or 'N' for each row. (where Y = user can edit, N = View/readonly)
I've tried a couple things to implement this. The best I've come up with is using the rowattr function, but my use is flawed since it hides the row in the grid (I don't want it hidden, just readonly):
function (rd) {
console.log('Row = '+rd.WWBPITM_SURROGATE_ID);
if (rd.ACCROLE === "N") {
console.log('RowAttr '+rd.ACCROLE);
return {"style": "display:none"};
}
This might be a start, but I'm not sure where to go from here and I'm not sure if I'm barking up the wrong tree with using rowattr.
I also tried using setCell in a loadComplete function, like this:
function GridComplete() {
var grid = $('#list1');
var rowids = grid.getDataIDs();
var columnModels = grid.getGridParam().colModel;
console.log('Check ACCROLE');
// check each visible row
for (var i = 0; i < rowids.length; i++) {
var rowid = rowids[i];
var data = grid.getRowData(rowid);
console.log('ACCROLE for '+rowid+' is '+data.ACCROLE);
if (data.ACCROLE == 'N') { // view only
// check each column
//console.log(data);
for (var j = 0; j < columnModels.length; j++) {
var model = columnModels[j];
if (model.editable) {
console.log('Is Editable? '+model.editable);
//grid.setCell(rowid, model.name, '', 'not-editable-cell', {editable: false, edithidden: true});
grid.setCell(rowid, model.name, '', 'not-editable-cell', {editoptions: { readonly: 'readonly', disabled: 'disabled' }});
}
}
}
}
}
But the editoptions don't seem to do anything with this.
Any ideas how to do this?
OK thanks for explaining about Form editing. Here's an example of how to prevent edits on certain records for jqGrid with form editing:
Start with this example of jqGrid form edit: http://www.ok-soft-gmbh.com/jqGrid/MulticolumnEdit.htm
Use the beforeInitData event to check your data before the edit form is displayed. Note that this is bound to the pager object.
Use getGridParam and getCell methods to get the current value you want. In my example I grabbed the client name
Add your own business logic for checking (I don't allow edits on 'test2')
Return false to prevent the edit form from popping up.
This example only handles edit, not insert or delete.
Replace $grid.jqGrid("navGrid", "#pager",...) from the example with this:
$grid.jqGrid("navGrid", "#pager", {view: true},
// Events for edit
{
beforeInitData: function (formid) {
var selectedRow = jQuery("#list").jqGrid('getGridParam','selrow'); //get selected rows
var selectedClient = $("#list").jqGrid('getCell', selectedRow, 'name');
if(selectedClient == 'test2')
{
alert('You are not allowed to edit records for client "' + selectedClient + '"');
return false;
}
}
},
// Events for add
{
beforeShowForm: function (formid) {
}
}
);
You didn't provide much information about how you're updating rows (there are various methods as described in JQGrid web page demos, but I took a guess as to a possible solution. I started with the example on the bottom of this page (trirand's web site wiki for inline_editing) http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing and made a few changes.
Added a new data column securityGroup, and put in data like 'A', 'B', 'C'
Displayed the new data column in the grid
The example used the onSelectRow event to start editing a row if you clicked on a new row. I updated this callback to check the value of row['securityGroup'], and only start .editRow if it's in securityGroupA
JSFiddle at http://jsfiddle.net/brianwoelfel/52rrunar/
Here's the callback:
onSelectRow: function(id){
var row = $(this).getLocalRow(id);
if(id && id!==lastsel2){
jQuery('#rowed5').restoreRow(lastsel2);
if(row['securityGroup'] == 'A') {
jQuery('#rowed5').editRow(id,true);
}
lastsel2=id;
}
},
If this method won't work for you, please provide more information about how you're currently doing edits with jqGrid. This example obviously is very trivial and doesn't even post to PHP or mysql or anything.
In case it will be helpful for others, here is how I am implementing Read Only rows in Form Editing mode, based on a column which designates what level of access the user has to each row:
In editoptions, use the beforeShowForm event, like so:
beforeShowForm: function (formid) {
console.log('Checking for READONLY '+formid.name);
var selectedRow = jQuery("#list1").jqGrid('getGridParam','selrow'); //get selected rows
var selRole = $("#list1").jqGrid('getCell', selectedRow, 'ACCROLE');
if(selRole == 'N' || selRole == 'S' || selRole == 'R')
{
//$("<div>Sorry, you do not have access to edit this record.</div>").dialog({title: "Access Denied"});
formid.find("input,select,textarea")
.prop("readonly", "readonly")
.addClass("ui-state-disabled")
.closest(".DataTD")
.prev(".CaptionTD")
.prop("disabled", true)
.addClass("ui-state-disabled");
formid.parent().find('#sData').hide();
var title=$(".ui-jqdialog-title","#edithd"+"list1").html();
title+=' - READONLY VIEW';
$(".ui-jqdialog-title","#edithd"+"list1").html(title);
formid.prepend('<span style="color: Red; font-size: 1em; font-weight: bold;">You viewing READONLY data.</span>');
}

Kendo grid enable editing during insert, disable during edit(applicable to only one column)

I have a scenario where I have a Kendo dropdown, Kendo Datepicker as couple of columns in the grid.
On Add new record, the dropdown should be editable, on Edit mode, this drop down should be non Editable.
I have declared Grid to be Editable in declaration using
.Editable()
model.Field(p => p.CountryName).Editable(true); // where CountryName is kendo dropdown
I am trying to do on Edit this way,
function OnEdit(e) {
if (e.model.isNew() == false) {
e.model.fields["CountryName"].editable = false
}
THe behaviour I observe is Initially on load, Editable is set to true (due to cshtml declaration). When I click on Edit too, the drop down is Editable because of the page load flag that is set.
Even though OnEditmethod is executed and editable is set to false, the grid seems to have loaded before this code execution, hence editable =false is not reflected.
If I click on Edit second time, now the editable is set to false due to the previous call, Hence the dropdown is non editable as expected.
In Summary, the flag setting is not effective for the current action, but for the immediate next action. I am not sure if I have made it clear. Can you guys help?
Update - The other option I tried, during databind to the grid, I tried explicitly settign editable to false to all the grid data. My assumption here was only the loaded rows will have this field set to false. But in this case even the add new record takes Editable false.
var grid2 = $("#Gridprepayment").data("kendoGrid").dataSource.data(requiredData);
$.each(requiredData, function (i, row) {
var model = $("#Gridprepayment").data("kendoGrid").dataSource.at(i);
if (model) {
model.fields["CountryName"].editable = false;
}
});
The best way is to make the column editable .
e.g.
model.Field(d => d.CountryName).Editable(true);
and Onedit function, replace the inner html like mentioned below, for just to display it as label.
function OnEdit(e) {
e.container[0].childNodes['0'].innerHTML = e.model.CountryName;
}
Try disabling the kendo dropdown in the following manner:
function OnEdit(e) {
if (e.model.isNew() == false) {
$("#CountryName").data("kendoDropDownList").enable(false);
}
}
You can try this if you want to show the dropdownList as label in edit mode
function OnEdit(e) {
if(e.container.find("input").attr("id") === 'CountryName') {
this.closeCell();
}
}
Note: The above code was written considering "CountryName" as the id of the dropdown. Please change if the id is different.
I tried this which worked.
It's only a work around :
function OnEdit(e) {
if (e.model.isNew() == false) {
if (e.container.find("input").attr("id") === 'CountryName') {
e.container.find("td:eq(0)").html($("#CountryName").val());
}
}
}

How to dynamically update other row fields in a KendoUI grid?

In my KendoUI datasource, I have the following defined:
change: function (e) {
if (e.action === "itemchange") {
// auto-format Display As
var geoDisplay, geoUrl;
if (e.items[0].GeoState.length > 0) {
geoDisplay = e.items[0].GeoCity + ", " + e.items[0].GeoState;
} else {
geoDisplay = e.items[0].GeoCity;
}
//this.dataItem(this.select()).GeoDisplay = geoDisplay;
e.items[0].GeoCity = "updated: " + e.items[0].GeoCity; // visually updates if editing this field
e.items[0].GeoDisplay = geoDisplay; // field is not updated
}
console.log("change: " + e.action);
console.log(e);
// do something else with e
},
Essentially I want to update other fields on a row being edited based on a field's input.
In this example, GeoCity is updated. The itemchange event is fired and only the GeoCity field gets updated with the new value. However I can see from the data that the other fields' data have been updated.
I have tried doing a .sync() and a few other methods to get this to appear, but no luck so far.
Incidentally, my grid is defined within an AngularJS directive and it's onEdit event isn't what I'm looking for, as I want the events that fire when each field is updated, not the whole row.
How can I get the other fields to visually update?
I managed to solve the issue by placing the following code in the data source code:
change: function (e) {
if (e.action === "itemchange") {
// auto-format Display As
var thisRow = $("#accountGeoLocationEditorGrid tbody").find(".k-grid-edit-row");
// update geo display
if (e.field === "GeoCity" || e.field === "GeoState") {
var geoDisplay, geoUrl;
if (e.items[0].GeoState.length > 0) {
geoDisplay = e.items[0].GeoCity + ", " + e.items[0].GeoState;
} else {
geoDisplay = e.items[0].GeoCity;
}
if (e.items[0].GeoDisplay.length == 0) {
e.items[0].GeoDisplay = geoDisplay;
thisRow.find("input[name=GeoDisplay]").val(geoDisplay);
}
}
}
I was really looking for another way to do this, as I don't really want to be doing DOM lookup, etc in a defined datasource.
Other suggestions welcome.
Did you try the grid refresh() method? At the end of your changes in the change event, call this line (with your grid's correct id):
$("#grid").data("kendoGrid").refresh();
I've tested this on my grid and kendo's samples and it works fine like this. You are editing the datasource but the grid is not aware of the extra changes you have done, except the cell that was edited. Calling refresh will update all the cells on the grid to reflect the datasource.

How to disable hyperlinks in jQGrid row

I am using a custom formatter to create hyperlinks in one of the columns of my grid.
In my code, there are cases when I need to disable the selected row. The row disabling works as I want it to, but the hyperlink for that row is not disabled. I can not select the row and all the other column values are displayed as grey colored to indicate that the row is disabled. The only column whose content does not change color is the one having links.
Any ideas on how to disable links?
This is my loadComplete function:
loadComplete: function (data) {
var ids =jQuery("#list").jqGrid('getDataIDs');
for(var i=0;i < ids.length;i++){
var rowId = ids[i];
var mod = jQuery("#list").jqGrid('getCell',ids[i],'mod');
if(mod=='y'){
jQuery("#jqg_list_"+rowId).attr("disabled", true);
$("#list").jqGrid('setRowData',ids[i],false, {weightfont:'bold',color:'silver'});
var iCol = getColumnIndexByName.call(this, 'adate');
$(this).jqGrid('doInEachRow', function (row, rowId, localRowData) {
$(row.cells[iCol]).children("a").click(function (e) {
e.preventDefault();
// any your code here
alert("No Good");
return false;
});
});
}
}
}
I want the links disabled in all the rows where the value of the column mod=y
You can try to use onClick callback of dynamicLink formatter described here, here and here. It gives you maximum flexibility. Inside of onClick callback you can test something like $(e.target).closest("tr.jqgrow").hasClass("not-editable-row") and just do nothing in the case.

Kendo - Grid - Remove Multiple Rows

I have the following code that remove rows that are checked (each row has a checkbox and I have a Filter button (and other buttons) in the toolbar).
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function(index) {
grid.removeRow($(this));
});
However, performance starts to become an issue when there are > 20 rows being removed. However, kendo filters (removes) 20 rows or more much faster. How is kendo filtering removing multiple rows from the view? Or is there some other better way to remove multiple rows from the grid? Thanks in advance for your help.
** Updated Fiddle to new location - Same code as before **
Try dealing with the data directly. Have the checkbox hooked to the row's Id and filter on that.
I linked a fiddle that removes array elements and then re-creates the grid. The 2 text boxes at the top of the grid capture the range of Ids that you want to remove (this would be the same array of your checkboxIds). Then I cycled through those "remove Ids", removed them from the data array and remade the grid.
I slightly modified a previous fiddle and that's why I'm re-creating the grid instead of dealing with the DataSource object directly. But I hope you get the gist of what I'm doing.
I have 1000 records in this example (only 3 columns) but it removes 950 records very quickly.
Fiddle- Remove from data array
Let me know if you need an example of this with the KendoUI DataSource object.
I included this code below because StackOverflow wouldn't let me post without it.
function filterData() {
var val1 = $("#val1").val();
var val2 = $("#val2").val();
var removeIndexes = new Array();
for (var i = val1; i <= val2; i++) {
removeIndexes.push(i);
}
$(removeIndexes).each(function(removeIndex) {
var removeItemId = this;
$(randomData).each(function(dataIndex) {
var continueLoop = true;
if (this.Id == removeItemId) {
randomData.splice(dataIndex, 1);
continueLoop = false;
}
return continueLoop;
});
});
createGrid();
}
You should use batch updates:
$("#resultsGrid").kendoGrid({
dataSource: {
batch: true,
...
}, ...});
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function() {
var dataItem = grid.dataItem(this);
grid.dataSource.remove(dataItem);
});
grid.dataSource.sync(); // this applies batched changes

Resources