jqGrid: Sending param with dataUrl - ruby-on-rails

I'm trying to create a dependent dropdown box. 'element' is dependent on 'grouping'.
My ajaxSelectOptions function seems to work, as 'temp' is passed, but then it isn't used by 'populate_element'. How can I use the 'temp' as my parameter :id?
My grid:
jQuery(document).ready(function(){
var lastsel;
var grid = jQuery("#list").jqGrid({
url:'codes/get_data.xml',
datatype: 'xml',
mtype: 'GET',
colNames:['ID', 'Version', 'Grouping', 'Element', 'Name'],
colModel:[
{name: 'id', index: 'id', hidden: true, editable: false },
{name: 'version', index: 'version',editable: true, editrules:{number:true}, cellEdit: true, search:true },
{name: 'grouping', index: 'grouping', editable: true, edittype: 'select', editoptions: {dataUrl: 'codes/populate_grouping.html'} },
{name: 'element', index: 'element', editable: true, edittype: 'select' }
],
pager: '#pager',
rowNum:200,
rowList:[50,100,200],
sortname: 'id',
sortorder: 'asc',
viewrecords: true,
height: 500,
scrollrows: true,
rownumbers: false,
caption: 'GL Codes',
editurl: 'codes/post_data.xml',
onSelectRow: function(id){
$("#list").setColProp('element', {editoptions: { dataUrl: 'codes/populate_element.html' }});
if(id && id!==lastsel){
$('#list').restoreRow(lastsel);
lastsel=id;
}
$('#list').editRow(id,true);
},
ajaxSelectOptions: {
data: {
temp: function(temp){
return grid.jqGrid('getGridParam', 'selrow')
}
}
}
});
Here is my error message:
Started GET "/codes/populate_element.html?temp=4" for 127.0.0.1 at 2012-09-27 17:18:33 +1200
Processing by CodesController#populate_element as HTML
Parameters: {"temp"=>"4"}
Completed 500 Internal Server Error in 1ms
ActiveRecord::RecordNotFound (Couldn't find Code without an ID):
app/controllers/codes_controller.rb:73:in `populate_element'
Update
I established that it was actually just a ruby syntax error in calling the param, rather than a jqGrid problem. For reference, I ended up calling it like so ... #code = Code.where(["id = ?",params[:temp]]).first

I think the problem is that you use wrong ids for the rows of grid. The error exist during filling of the grid. The most easy way to fix the problem will be to add key: true property to the definition of the 'id' column in colModel. In the case the value from the column id will be used as the rowid: the value of id attribute of rows (<tr>) of the grid.

Related

jqgrid TreeGrid unable to see content of expanded column

I have problem while rendering expanded column text while using jQuery jqgrid's treegrid type. Here's my treegrid definition and the response from server, I'll be happy if someone can help me?
Thanks in advance.
Javascript
menuGrid.jqGrid({
url:'kullanici/loadMenu.ajax',
//enable TreeGrid
treeGrid: true,
//set TreeGrid model
treeGridModel: 'adjacency', //'nested', //'adjacency',
//set expand column
ExpandColumn: 'Text',
width: 550,
datatype: 'json',
viewrecords: true,
loadonce: true,
colNames: ['ID', 'Text'],
colModel: [
{ name: 'id', index: 'id', width: 20, align: 'left', editable: false, key: true, sorttype:'int', hidden: false },
{ name: 'Text', index: 'menuName', width: 120, sortable: true, align: 'left' }
],
jsonReader: {
repeatitems : false,
id: 'id'
},
sortname: 'id',
sortorder: 'asc',
height: 200,
sortable: true,
enabletooltips: true,
caption: 'Menü Ağacı'
});
menuGrid.jqGrid('navGrid','#paddtree');
The JSON response from server
{"rows":[{"expanded":true,"id":1,"isLeaf":false,"level":0,"loaded":true,"text":"Kullanici Islemleri"},{"expanded":false,"id":2,"isLeaf":true,"level":1,"loaded":true,"parent":1,"text":"Kullanici Ekle"},{"expanded":false,"id":3,"isLeaf":true,"level":1,"loaded":true,"parent":1,"text":"Kullanici Duzenle"},{"expanded":false,"id":4,"isLeaf":true,"level":1,"loaded":true,"parent":1,"text":"Kullanici Sil"},{"expanded":true,"id":5,"isLeaf":false,"level":0,"loaded":true,"text":"Fatura ??lemleri"},{"expanded":false,"id":6,"isLeaf":true,"level":1,"loaded":true,"parent":5,"text":"Fatura Goruntule"}],"records":6,"success":true}
Your Json response must be as follows :
{"rows":[
{
"id":1,
"text":"Kullanici Islemleri"
"level":0,
"isLeaf":false,
"parent" : "null" //If the row is at 0-lvl
"expanded":true,
"loaded":true,
},
],"records":6,"success":true}
You have to respect the order of the grid cols.
First, your data cols, then, level,isLeaf, parent,expanded. I'm not sure about the loaded field, try with and without.
OK,I have found the solution, colNames, colModel and ExpandColumn configs should match(case-sensitive). As I said above the order of config isn't important.

Simple jqgrid Delete in 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
);

How to pass form data and jqGrid (editUrl) data to Controller at same time

I have an asp.net MVC3 app with various bits of form data and a jqGrid.
When I edit a row in the jqGrid I need to post the grid data as well as some of the form pieces to the editUrl controller.
I can post the jqGrid edited data to my controller through the editUrl just fine.
Is there a way to do this?
Im not sure how to send the other form elements and how to receive them in my controller.
Any help will be greatly appreciated.
Below is my jqGrid:
$("#jqTable").jqGrid({
// Ajax related configurations
url: '#Url.Action("_CustomBinding")',
datatype: "json",
mtype: "POST",
postData: {
programID: function () { return $("#ProgramID option:selected").val(); },
buildID: function () { return $('#Builds option:selected').val(); }
},
// Specify the column names
colNames: ["Actions", "Assembly ID", "Assembly Name", "Assembly Type", "Cost", "Order", "Budget Report", "Partner Request", "Display"],
// Configure the columns
colModel: [
{ name: 'myac', width: 80, fixed: true, sortable: false, resize: false, formatter: 'actions', formatoptions: { keys: true} },
{ name: "AssemblyID", key: true, index: "AssemblyID", width: 40, align: "left", editable: false },
{ name: "AssemblyName", index: "AssemblyName", width: 100, align: "left", editable: true, edittype: 'select',
editoptions: {
dataUrl: '#Url.Action("_Assemblies")',
buildSelect: function (data) {
var response = jQuery.parseJSON(data);
var s = '<select>';
if (response && response.length) {
for (var i = 0, l = response.length; i < l; i++) {
var ri = response[i];
s += '<option value="' + ri + '">' + ri + '</option>';
}
}
return s + "</select>";
}
}
},
{ name: "AssemblyTypeName", index: "AssemblyTypeName", width: 100, align: "left", editable: false, edittype: 'select' },
{ name: "AssemblyCost", index: "AssemblyCost", width: 50, align: "left", formatter: "currency", editable: true },
{ name: "AssemblyOrder", index: "AssemblyOrder", width: 50, align: "left", editable: true },
{ name: "AddToBudgetReport", index: "AddToBudgetReport", width: 100, align: "center", formatter: "checkbox", editable: true, edittype: 'checkbox' },
{ name: "AddToPartnerRequest", index: "AddToPartnerRequest", width: 100, align: "center", formatter: "checkbox", editable: true, edittype: 'checkbox' },
{ name: "Show", index: "Show", width: 50, align: "center", formatter: "checkbox", editable: true, edittype: 'checkbox'}],
// Grid total width and height and formatting
//width: 650,
//height: 220,
altrows: true,
// Paging
//toppager: true,
pager: $("#jqTablePager"),
rowNum: 10,
rowList: [10, 20, 30],
viewrecords: true, // Specify if "total number of records" is displayed
emptyrecords: 'No records to display',
// Default sorting
sortname: "AssemblyID",
sortorder: "asc",
// Grid caption
caption: "Build Template",
// grid command functionality
editurl: '#Url.Action("_AjaxUpdate")',
onSelectRow: function (AssemblyID) {
if (AssemblyID && AssemblyID !== lastsel) {
$('#jqTable').jqGrid('restoreRow', lastsel);
$("#jqTable").jqGrid('editRow', AssemblyID, true);
lastsel = AssemblyID;
}
}
}).navGrid("#jqTablePager",
{ refresh: false, add: false, edit: false, del: false },
{}, // settings for edit
{}, // settings for add
{}, // settings for delete
{sopt: ["cn"]} // Search options. Some options can be set on column level
);
You can customize what is being sent to the server using onclickSubmit option:
.navGrid("#jqTablePager",
{ refresh: false, add: false, edit: false, del: false },
{ // settings for edit
onclickSubmit: function(params, postdata)
{
postdata.extraParam = 'value'
}
},
{}, // settings for add
{}, // settings for delete
{sopt: ["cn"]} // Search options. Some options can be set on column level
);
The controller will receive a JSON object containing all edited properties + extraParam. It is up to you how you handle this on the server side.
I see you use already programID and buildID properties defined as functions. The functions will be called during every request to get the data for the grid. In the same way you can use inlineData or extraparam parameter of the editRow which you call explicitly inside of your onSelectRow callback.
Try to call the demo which has the following jqGrid options:
inlineData: {
myParam: function () {
alert("inlineData is calling!!!");
return "OK";
}
},
onSelectRow: function (id) {
if (id && id !== lastSel) {
$(this).jqGrid('restoreRow', lastSel);
$(this).jqGrid('editRow', id, true, null, null, null, {
myNextParam: function () {
alert("extraparam of 'editRow' is calling!!!");
return "Fine";
}
});
lastSel = id;
}
}
You will see two alerts if you would save the data of the editing row. In my demo I used editurl: 'myDummyUrl' which has no code on the server side and you will see an error at the end, but if you examine the HTTP traffic (with respect of Fiddler or Firebug) you will see that the following additional parameters will be send to the editurl:
myParam=OK&myNextParam=Fine
I think it is what you need.
inlineData:{}
is working fine for getting work before goes to controller while editing.
But in case of delete how to get event like before to pass control to controller to make json , after click on delete.

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(','));.

jqgrid MVC omit some columns from ModelState

I have a jqGrid in MVC setup as:
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery("#list").jqGrid({
url: '/Home/DynamicGridData/',
datatype: 'json',
mtype: 'POST',
colNames: ['id', 'note', 'tax', 'PaymentType', 'CreatedByUsername', 'Actions'],
colModel: [
{ name: 'id', index: 'id', hidden: true, key: true, editable: true, editrules:{ required:false } },
{ name: 'note', index: 'note', width: 40,align:'center', editable: true, editrules: { required : true } },
{ name: 'tax', index: 'tax', width: 400, align: 'center', editable: true, editrules: { required : true } },
{ name: 'PaymentTypeId', index: 'PaymentTypeId', width: 400, align: 'center', editable: true, edittype:"select",
editoptions: { dataUrl: '/Home/PaymentTypes/' }},
{ name: 'CreatedByUsername', index: 'CreatedByUsername', hidden: true, editable: true, editrules:{ required:false } },
{ name: 'act',index:'act',width:55,align:'center',sortable:false,formatter:'actions',
formatoptions:{
keys: true, // we want use [Enter] key to save the row and [Esc] to cancel editing.
beforeSubmit:function(postdata, formid) {
alert("Hi");
jQuery("#ValidationSummary").show('slow');
},
},}
],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
imgpath: '',
caption: 'My first grid',
editurl: '/Home/Save/'
});
jQuery("#list").navGrid('#pager', { edit: false, search: false, add: true });
});
</script>
When creating on submit it goes to the save method on the controller.
As you can see CreatedByUsername and id are hidden for normal view and edit.
When I add new data though I find that ModelState.IsValid = false.
I've managed to make it so that CreatedByUsername does not added an error to the ModelState even though no data is added for it on insert through editrules:{ required:false }.
The problem is this same piece of code doesn't work for the id and is adding an Error to the ModelState of "The id field is required."
Can anyone please tell me how to prevent this from happening for the id field?
The problem is that your id field has the key attribute and besides your validation rule this field is required. A workaround is to define a custom function for validation an always return true
Can you set the id field in your viewmodel to nullable? Like this:
public int? Id { get; set; }
If the id is not nullable, mvc will automatically create a validation error. If you're not using a viewmodel, but just using parameters on your save action, you can set the id parameter to nullable.

Resources