Simple jqgrid Delete in MVC - asp.net-mvc

I've been trawling across the web for answers, and maybe it's a case of it being more complicated than I expect (or I just don't understand the solutions), but I am looking for a way to simply delete a selected row from my jqgrid by clicking the trash icon.
Currently my grid is being populated with Linq to SQL data.
Here is my grid:
jQuery("#grid").jqGrid({
url: '<%= ResolveUrl("~/Home/GetData") %>',
datatype: "json",
mtype: 'GET',
postData: { DDLid: function () { return jQuery("#DDL option:selected").val(); } },
colNames: ['Col1', 'Col2'],
colModel: [
{ name: 'Col1', index: 'Col1', width: 200, editable: false },
{ name: 'Col2', index: 'Col2', width: 200, editable: false }
],
jsonReader: {
repeatitems: false
},
rowNum: 10,
pager: jQuery('#gridpager'),
sortname: 'Type',
viewrecords: true,
sortorder: "asc",
caption: "Table"
}).navGrid('#gridpager', { del: true, add: false, edit: false, search: false }, {}, {}, {url: "Delete"});
Now the 'id' in post data is NOT the primary key in this table - I just need it to help populate the grid.
What I would like to get is the selected row id and pass it to the Delete method, but I can't find any way to do that.
I have tried using jQuery("#grid").getGridParam('selrow') in the postData but it always returns null.
Any help would be greatly appreciated.
Here is my delete method, for reference:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int DDLid)
{
int row = Convert.ToInt32(/*I NEED THIS ID*/);
var query = from x in _ctx.DataTable
where ((x.id == row))
select x;
_ctx.DataTable.DeleteOnSubmit(query.Single());
_ctx.SubmitChanges();
return Json(true);
}
This method is called and is fine, but I am getting the wrong id. I need the selected row's id. This breaks because the DDLid returns more than one row (since it is used to populate the grid).
I hope that makes sense.

I discovered where I would pass the selected index (but then I realised I was looking for the primary key, rather than selected index, but it is the same result regardless)
I needed to add this to my navGrid:
{url: "Delete", mtype: "POST", reloadAfterSubmit: true,
serializeDelData: function (postdata) {
var selectedrowindex = jQuery("#grid").jqGrid('getGridParam', 'selrow');
var dataFromCellByColumnIndex = jQuery('#grid').jqGrid ('getCell', selectedrowindex , 1);
return {DDLid: postdata.id, name: dataFromCellByColumnIndex};
}
});
So this passes a column value to my delete method as well as the DDLid, but I could easily swap dataFromCellByColumnIndex with selectedrowindex.

You should just implement Delete action having id parameter:
public JsonResult Delete(string id) {
...
}
To reference the action in the JavaScript code I would use 'url: <%= Url.Action("Delete") %>' instead of url: "Delete" which you use currently.
You can download here demo project which I created for the answer. The project implement deleting of the row together with many other features which you currently not need.

You can make another post inside delete method with your own params. After defining grid, you can define each action in detail. It is posting actual delete with correctid and original one is posting fake id. JQgrid is using row count for delete not the primary key. They may change it with recent versions, but this was working Jqgrid 3.8
jQuery("#ClientGrid").jqGrid('navGrid', '#ClientGridPager',
{ view: true, edit: true, search: false }, //options
{height: 240, caption: 'Edit Client', beforeShowForm: hideIDColumn, reloadAfterSubmit: true, mtype: 'POST', url: "/Settings/EditClient", jqModal: false, closeOnEscape: true, bottominfo: "Fields marked with (*) are required" }, // edit options
{height: 340, caption: 'Add Client', beforeShowForm: hideIDColumn, reloadAfterSubmit: true, mtype: 'POST', url: "/Settings/CreateClient", jqModal: false, closeOnEscape: true, bottominfo: "Fields marked with (*) are required", closeAfterAdd: true }, // add options
//delete method
{reloadAfterSubmit: true, beforeSubmit: function (postdata, formid)
{
var lastselectedID = -1;
if (ClientGridrow != null || typeof (ClientGridrow) != "undefined")
{
lastselectedID = $("#ClientGrid").getCell(ClientGridrow, 'ID_PK');
}
//CUSTOME delete to send taskid instead of rowid
$.ajax({ type: "POST", url: "/Settings/DeleteClient/?objid=" + lastselectedID,
data: "", success: function (response)
{
$("#ClientGrid").trigger("reloadGrid"); //reloadAfterSubmit: true is not working in Chrome
}
});
return [true, "Delete failed message"];
}, caption: 'Delete Client', datatype: 'local', url: "/Settings/DeleteClient/?objid=-1", jqModal: false, closeOnEscape: true
}, // del options..we make two posts
{closeOnEscape: true }, // search options
{height: 230, width: 350, jqModal: false, closeOnEscape: true} // view options
);

Related

Delete, No url is set in jqgrid

I'm using jqgrid and when deleting a row in the grid i get the alert "Delete selected record?" and when i click ok i have written a code in onClickSubmit to make a ajax call to the controller which takes some parameters and delete the record. The functionality works fine.
But when i click "Delete" button in the alert i get an error "No url is set". Now, i have a url inside my ajax call which does the function. Why is the error thrown?
jqGrid:
var selectedRowId = "125";
$("#AttachmentsGrid").jqGrid({
url: '#Url.Action("LoadTransactionAttachments", "Home")',
postData: { 'transactionId': selectedRowId },
mtype: 'GET',
datatype: 'json',
jsonReader: {
id: 'AttachmentId',
repeatitems: false
},
height: 'auto',
hidegrid: false,
rownumbers: true,
autowidth: true,
shrinkToFit: false,
rowNum: 10,
pager: '#AttachmentsPager',
caption: "Attachments",
colNames: ['AttachmentName'],
colModel: [{ name: 'AttachmentName', index: 'AttachmentName', formatter: imageFormatter, unformat: imageUnFormatter }],
beforeRequest: function () {
responsive_jqgrid($(".jqGrid"));
},
onSelectRow: function (id) {
var statusId;
attachmentId = id;
var selectValues = jQuery('#AttachmentsGrid').jqGrid('getRowData', id);
attachmentName = selectValues.AttachmentName;
if (accessLevel.HasDeleteAttachmentAccess == true)
$("#del_AttachmentsGrid").show();
else
$("#del_AttachmentsGrid").hide();
},
loadComplete: function () {
UnBlockUI();
}
});
jQuery("#AttachmentsGrid").jqGrid('navGrid', '#AttachmentsPager', {
edit: false, add: false, del: true, search: false, refresh: true, refreshtext: ""
}, {}, {}, {
// url: '#Url.Action("UpdateDummyData", "Home")',
// Delete attachment event.
onclickSubmit: function (response, postData) {
$.ajax({
url: '#Url.Action("DeleteSelectedTransactionAttachment", "Home")',
datatype: 'json',
data: { 'attachmentId': JSON.stringify(postData), 'attachmentName': attachmentName, 'transactionId': selectedRowId },
type: 'POST',
success: OnCompleteDeleteAttachments,
error: function (xhr, status, error) {
if (xhr.statusText == "Session TimeOut/UnAuthorized") {
alert(xhr.statusText);
window.location.href = '#Url.Action("LogOut", "Account")';
}
else
alert(xhr.responseText);
}
});
It works when i give some Dummy url in delete method which i dont need. I need another way to solve this.?
FYI, This happens for me also during the edit of a row using form editing.
It seems to me that you try to use Delete in a wrong way. What you do is making Ajax request to '#Url.Action("DeleteSelectedTransactionAttachment", "Home")' with some additional data, do some unknown additional action inside of OnCompleteDeleteAttachments in case of successful deleting and do additional error handling in case of "Session TimeOut/UnAuthorized" error in statusText.
I think that correct implementation should looks more as the following
jQuery("#AttachmentsGrid").jqGrid('navGrid', '#AttachmentsPager', {
edit: false, add: false, search: false, refreshtext: ""
}, {}, {}, {
url: '#Url.Action("DeleteSelectedTransactionAttachment", "Home")',
serializeDelData: function (postData) {
return {
attachmentId: JSON.stringify(postData),
attachmentName: attachmentName,
transactionId: selectedRowId
}
},
errorTextFormat: function (xhr) {
if (xhr.statusText == "Session TimeOut/UnAuthorized") {
window.location.href = '#Url.Action("LogOut", "Account")';
} else {
return xhr.responseText;
}
},
afterSubmit: OnCompleteDeleteAttachments
});

jqGrid navigation button fired post method?

jqGrid
$(document).ready(function () {
$("#grid").jqGrid({
url: '#Url.Action("GetAllAuthors", "Admin")',
datatype: "json",
mtype: 'get',
colNames: ['Yazar Adı', 'Öz Geçmiş'],
colModel: [
{ name: 'Name', index: 'Name', editable: false },
{ name: 'Description', index: 'Description', editable: false }
],
jsonReader: {
repeatitems: false,
id: "sno",
root: "rows", //array containing actual data
page: "page", //current page
total: "total", //total pages for the query
records: "records", //total number of records
repeatitems: false
},
rowNum: 10,
rowList: [10, 20, 30, 40, 50],
pager: jQuery('#gridpager'),
sortname: 'Name',
viewrecords: true,
sortorder: "asc",
width: 710,
height: 300
})
.navGrid('#gridpager', { edit: false, add: false, del: false, search: false, refresh: false })
.navButtonAdd('#gridpager', {
caption: "Düzenle",
buttonicon: "ui-icon-pencil",
onClickButton: function () {
var grid = $("#grid");
var rowid = grid.jqGrid('getGridParam', 'selrow');
//alert(rowid + " - " + grid.jqGrid('getCell', rowid, 'CustomerName') + " - Link: " + $("#customers_grid_table a.customer_details").attr("href"));
window.location = '#Url.Action("EditAuthor", "Admin")?authorId=' + rowid;
//LoadAction('#Url.Action("EditAuthor", "Admin")?authorId=' + rowid);
}
}); //end jqgrid
});
I have two method in my controller
Get method
[HttpGet]
public ActionResult EditAuthor(int authorId)
Post method
[HttpPost]
public ActionResult EditAuthor(AuthorViewModel model, HttpPostedFileBase file)
I selected a row and clicked edit button, I expect to fire get method, but post method is fired. What can I do to fire get method?
Thanks.
If you set new value of window.location the HTTP GET will be used. To produce HTTP POST you can either use $.ajax or submit some form. You can for example dynamically build invisible <form> and submit it. For example
onClickButton: function () {
var rowid = $(this).jqGrid("getGridParam", "selrow"),
myForm = document.createElement("form"),
param1 = document.createElement("input");
myForm.action = '#Url.Action("EditAuthor", "Admin")';
myForm.method = "POST";
myForm.style.display="none";
param1.name = "authorId";
param1.type = "text";
param1.value = rowid;
myForm.appendChild(param1);
document.body.appendChild(myForm);
myForm.submit();
document.body.removeChild(myForm);
}
I recommend you additionally to include additional validation whether some row is selected (whether rowid is not null).
Moreover I recommend you
to use always gridview: true option in the grid which will just improve the performance of the grid.
replace the option pager: jQuery('#gridpager') to pager: '#gridpager'.
replace the current value of jsonReader option to jsonReader: {repeatitems: false, id: "sno"}. The options which you specify will be combined with default value (see the documentation). Additionally your current value of jsonReader option contains syntax error because you specify the same property repeatitems: false twice.

jqGrid: pass selected IDs as HTML form parameters

I have an HTML form (Razor) with jqGrid to select entities (please assume customers, for example).
The customers jqGrid looks like:
jQuery("#ajaxGrid").jqGrid({
url: '#Url.Action("CustomersData")',
datatype: 'json',
mtype: 'GET',
jsonReader: { repeatitems: false, id: "Id" },
colNames: ['Id', 'Name'],
colModel: [
{ name: 'Id', editable: true, sortable: false, hidden: false },
{ name: 'Name', editable: true, sortable: false, hidden: false }
],
multiselect: true,
viewrecords: true,
rowNum: 5,
width: '850',
height: '15em'
});
So, the grid allows multiple selection.
The question is: how to pass selected customer IDs (as IEnumerable) to the controller on submit (to the appropriate submit action)?
I guess it can be done by setting all selected IDs as form parameter. I don't know how to copy the data from the array:
var ids = jQuery("#ajaxGrid").getGridParam('selarrrow');
to HTML form hidden value.
If I understand you correct you can for example create string with comma-separated ids of selected rows with respect of ids.join(','). Then you can use the jQuery.val(newValue) to set the new halue to the hidden field: $("#hiddenFieldId").val(ids.join(','));.

Need help with jqGrid and navGrid

With the main part of the jqGrid there is the postData parameter that can be set to add stuff to the POST variable. Is there a way I could do the same thing with the navGrid?
Here is what I have:
main jqGrid script
$("#"+id).jqGrid({
url:baseURL+'modules/'+module+'/config.php',
postData: {event: 'load-content',content : id,module: module},
datatype: 'json',
mtype: 'POST',
colNames:colNames,
colModel:colModel,
pager: '#pager',
rowNum:limit,
rowList:[10,20,30],
autowidth: true,
sortname: sortby,
sortorder: 'desc',
gridview: true,
viewrecords: true,
caption: title,
editurl: baseURL+'modules/'+module+'/config.php'
});
navGrid script
jQuery("#"+id).jqGrid('navGrid','#pager',
{del:true,add:true,edit:true}, //options
{height:280,reloadAfterSubmit:false}, // edit options
{height:280,reloadAfterSubmit:false}, // add options
{reloadAfterSubmit:false}, // del options
{});
What I want is to add {module: module, event: 'del-test'} to the POST of the delete button.
You can use additional editData (for add or edit operations) or delData parameter (for delete operation) and change the del options used as a parameter of 'navGrid' from
{reloadAfterSubmit:false}
to
{reloadAfterSubmit:false, editData:{module: module, event: 'del-test'}}
(the variable module should be defined before).
By the way, like with postData parameter (see this old answer) you can use function for any property of editData parameter:
{
reloadAfterSubmit:false,
delData: {
module: function() {
return "bla bla";
},
event: 'del-test'
}
}
I know it's a long time since you posted this question, I wanted to improve it anyways the wiki pages shows you the basic use of the navgrid and this is the answer that worked for me.
Best regards,
Modify your code this way
$("#" + id).jqGrid('navGrid', '#pager',
{ add: true, edit: true, del: true },
{ height:280, reloadAfterSubmit:false },
{ height:280, reloadAfterSubmit:false },
{
// settings for Delete
mtype: "post",
reloadAfterSubmit: false,
onclickSubmit: function (rp_ge, postdata) {
rp_ge.url = '<%: Url.Content("~/URL/TO/DELETE/METHOD/HERE") %>' + postdata;
},
serializeDelData: function (postdata) {
postdata.module = module;
postdata.event = 'del-test';
return postdata;
}
},
{},
{}
);

How to implement search on jqgrid?

So I've got basic example of jqgrid working in ASP.NET MVC, the javascript looks like this:
$(document).ready(function() {
$("#list").jqGrid({
url: '../../Home/Example',
datatype: 'json',
myType: 'GET',
colNames: ['Id', 'Action', 'Parameters'],
colModel: [
{ name: 'id', index: 'id', width: 55, resizable: true },
{ name: 'action', index: 'action', width: 90, resizable: true },
{ name: 'paramters', index: 'parameters', width: 120, resizable: true}],
pager: $('#pager'),
rowNum: 10,
rowList: [10, 20, 30],
sortname: 'id',
sortorder: 'desc',
viewrecords: true,
multikey: "ctrlKey",
imgpath: '../../themes/basic/images',
caption: 'Messages'
});
Now I am trying to implement the search button that they have in the jqgrid examples (click on Manipulating/Grid Data). But I don't see how they implement it. I'm expecting e.g. a "search:true" and a method to implement it.
Has anyone implemented search on jqgrid or know of examples that show explicitly how to do it?
I recently implemented this myself (yesterday actually) for the first time. The biggest hurdle for me was figuring out how to write the controller function. The function signature is what took me the longest to figure out (notice the _search, searchField, searchOper, and searchString parameters as those are missing from most of asp.net mvc examples I've seen). The javascript posts to the controller for both the initial load and for the search call. You'll see in the code that I'm checking whether the _search parameter is true or not.
Below is the controller and the javascript code. My apologies for any formatting issues as this is my first time posting on here.
public ActionResult GetAppGroups(string sidx, string sord, int page, int rows, bool _search, string searchField, string searchOper, string searchString)
{
List<AppGroup> groups = service.GetAppGroups();
List<AppGroup> results;
if (_search)
results = groups.Where(x => x.Name.Contains(searchString)).ToList();
else
results = groups.Skip(page * rows).Take(rows).ToList();
int i = 1;
var jsonData = new
{
total = groups.Count / 20,
page = page,
records = groups.Count,
rows = (
from appgroup in results
select new
{
i = i++,
cell = new string[] {
appgroup.Name,
appgroup.Description
}
}).ToArray()
};
return Json(jsonData);
}
And here is my HTML/Javascript:
$(document).ready(function() {
$("#listGroups").jqGrid({
url: '<%= ResolveUrl("~/JSON/GetAppGroups/") %>',
datatype: 'json',
mtype: 'GET',
caption: 'App Groups',
colNames: ['Name', 'Description'],
colModel: [
{ name: 'Name', index: 'Name', width: 250, resizable: true, editable: false},
{ name: 'Description', index: 'Description', width: 650, resizable: true, editable: false},
],
loadtext: 'Loading Unix App Groups...',
multiselect: true,
pager: $("#pager"),
rowNum: 10,
rowList: [5,10,20,50],
sortname: 'ID',
sortorder: 'desc',
viewrecords: true,
imgpath: '../scripts/jqgrid/themes/basic/images'
//});
}).navGrid('#pager', {search:true, edit: false, add:false, del:false, searchtext:"Search"});
See my article on codeproject, which explains how we can do multiple search in jqgrid:
Using jqGrid’s search toolbar with multiple filters in ASP.NET MVC
I use IModelBinder for grid's settings binding, expression trees for sorting and filtering data.
In case you're still wondering about dealing with optional parameters, just declare them as nullables by adding a ? after the type name.
Now you'll be able to compare them with null to check if they are absent.
Note that you don't need to do this with strings, as they are already nullable.
#Alan - ok, I used your method and extended my webservice to expect those additional three parameters and check for "_search" is true/false. But, in order to make this work, I had to add this to my ajax call in the JavaScript:
if (!postdata._search) {
jQuery("#mygrid").appendPostData( {searchField:'', searchOper:'', searchString:''});
}
Just follow this link. It has all implementations explained...
You can create a button searchBtn and can invoke search form on click
$("#searchBtn").click(function(){
jQuery("#list4").searchGrid(
{options}
)});

Resources