Related
I have 2 requirements I need to solve for. I'm using a JQGrid on an aspx page with other form controls. Saving the main form generates a database id that is populated in a hidden field. If the hidden field is empty, I don't want to save the grid record because I need the db id first. If the hidden field has a value, I want to save the row with a editurl.
The second part is related to a Bootstrap multiselect in one of the grid columns (I need the filtering capability). When a user selects a value from the multiselect I'd like to populate the PERNR column with the value selected. I can't use the onchange event for the multiselect since if the user doesn't change from the first option obviously it won't trigger the event.
How can I solve these 2 issues?
var roleDdlItems = $.parseJSON($("input[id$='hdfRoleDdlItems']").val());
$("#grdParticipants").jqGrid({
jsonReader: {
repeatitems: false,
root: 'Table',
page: function (obj) { return 1; },
total: function (obj) { return 2; },
records: function (obj) { return obj.ItemCount; },
id: "0"
},
caption: getParticipantCaption(),//"Participants",
pgbuttons: false,
recordtext: "Total: {2}",
emptyrecords: "",
loadtext: "Loading...",
pgtext: "",
datatype: function () {
UpdateParticipant("getParticipants");
},
ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
// serializeGridData: function (postData) { return JSON.stringify(postData); },
colNames: ['Id', 'PERNR', 'Name', 'Email', 'RoleId', 'Role', 'Active', 'Updated'],
colModel: [
{ name: 'Id', index: 'Id', hidden: true, editable: true, hidedlg: true },
{ name: 'PERNR', index: 'PERNR', hidden: true, editable: true, hidedlg: true },
{ name: 'Name', index: 'Name', width: 200, align: "center", editable: true, edittype: "select",
editoptions: { value: function () {
var ITDdlItems = $.parseJSON($("input[id$='hdfITEmployeesDdlItems']").val());
var s = "";
if (ITDdlItems.Table4 && ITDdlItems.Table4.length) {
for (var i = 0, l = ITDdlItems.Table4.length; i < l; i++) {
var item = ITDdlItems.Table4[i];
s += item.PERNR + ":" + item.Name + ";";
}
}
s = s.substring(0, s.length - 1);
return s;
},
dataInit: function (e) {
$(e).multiselect({
maxHeight: 200,
enableFiltering: true,
filterPlaceholder: "Search Employees",
enableCaseInsensitiveFiltering: true,
templates: {
filter: '<li class="multiselect-item filter"><div class="input-group"><input class="form-control input-sm multiselect-search" id="txtITEmployeeFilter" type="text"></div></li>',
filterClearBtn: "<span class='input-group-btn'><button class='btn btn-default input-sm multiselect-clear-filter' type='button'><i class='glyphicon glyphicon-remove'></i></button><button class='btn btn-primary input-sm multiselect-clear-filter' type='button' onclick='javascript:searchEmployees("#" + e.id + "");'><i class='glyphicon glyphicon-search'></i></button></span>"
},
onDropdownHide: function (event) {
$(e).multiselect("updateButtonText");
$(e).multiselect("updateSelectAll");
}
// onChange: function(option, checked) {
// var selectedOption = $("#" + e.id + " option:selected").val();
// alert(selectedOption);
// }
});
}
}
},
{ name: 'Email', index: 'Email', width: 250, align: "center", editable: false },
{ name: 'RoleId', index: 'RoleId', hidden: true, editable: true, hidedlg: true },
{ name: 'Role', index: 'Role', width: 175, align: "center", editable: true, edittype: "select",
editoptions: { value: function () {
var roleDdlItems = $.parseJSON($("input[id$='hdfRoleDdlItems']").val());
var s = "";
if (roleDdlItems.Table3 && roleDdlItems.Table3.length) {
for (var i = 0, l = roleDdlItems.Table3.length; i < l; i++) {
var item = roleDdlItems.Table3[i];
s += item.Id + ":" + item.Role + ";";
}
}
s = s.substring(0, s.length - 1);
return s;
},
dataInit: function (e) {
$(e).multiselect({
maxHeight: 200,
onDropdownHide: function (event) {
$(e).multiselect("updateButtonText");
$(e).multiselect("updateSelectAll");
}
});
}
}
},
{
name: 'Active', index: 'Active', hidden: false, width: 75, align: "center", editable: true, hidedlg: true,
edittype: 'checkbox', editoptions: { value: "true:false", defaultValue: "Active" },
formatter: "checkbox", formatoptions: { disabled: true }
},
{ name: 'Updated', index: 'Updated', width: 100, align: "center", editable: false, sorttype: "date",
formatter: 'date', formatoptions: { newformat: 'n/j/y g:i A' }
}
],
rowNum: 5000,
autoWidth: true,
rowList: [],
pager: '#pgrParticipants',
toppager: true,
sortname: 'Name',
viewrecords: true,
sortorder: 'asc'
});
$('#grdParticipants').navGrid("#pgrParticipants", {edit: false, add: false, del: true, refresh: false, search: false, view: false});
$('#grdParticipants').inlineNav('#pgrParticipants',
// the buttons to appear on the toolbar of the grid
{
edit: true,
add: true,
del: true,
cancel: true,
editParams: {
keys: true
},
addParams: {
addRowParams: {
keys: true
}
}
});
$('#grdParticipants').navSeparatorAdd('#pgrParticipants', {
sepclass: 'ui-separator',
sepcontent: '',
position: 'last'
});
$('#grdParticipants').navButtonAdd('#pgrParticipants',
{
buttonicon: "ui-icon-help",
title: "Roles & Responsibilities Matrix",
caption: "Roles & Responsibilities Matrix",
position: "last",
onClickButton: showRoleMatrix
});
* EDIT *
The datatype function contains an ajax call that populates the grid. I’m using this based on an example someone else in my company provided. I’ll look around today for a better method, as it sounds this isn’t the best way. Maybe using url, which I stumbled across today.
This is a tab interface to track outages that will ultimately have a total of 5 separate JQGrids. When the page initially loads for a new outage this grid is on the first tab and is empty. It would only contain records if they’re editing an existing outage. In that instance, I would populate values in the main outage form controls and load data in the grid. The UpdateParticipant function seemed work well for this as it allows me to check for that hidden field before deciding whether a db call is even needed.
The PERNR is an employee id that the user doesn’t need to know, hence hidden. It’s not strictly confidential info, but we don’t advertise it either. They only need to see Name and Email (maybe) based on the value selected from the Name multiselect. Id will be a Participant Id generated by the database after the grid data is saved. Which can’t happen until the main outage form above is saved because I need that unique Outage Id as a foreign key for the participants. This attaches a participant to an outage and becomes the unique Id for the grid rows.
The selectedOption = $("#" + e.id + " option:selected").val() is commented out, but was only to trigger onchange for that specific Bootstrap Multiselect. The Role multiselect didn’t have an onchange function registered in code. So yes, it was for one element only. As mentioned previously, I was trying to use this to populate PERNR on a Name select. I need PERNR not Name to save to the db later. To solve for this I’m using the custom formatter on that column so I’ve since removed that onchange function for the Name multiselect. The ITDdlItems = $.parseJSON($("input[id$='hdfITEmployeesDdlItems']").val()) contains a json list of employee names and PERNRs to populate the Name multiselect. That works fine so this isn’t code relevant.
The only thing I need to figure out is how to perform a check for OutageId in the hidden field before the grid data is posted to the server. Thinking about it last night, if all else fails, I’ll let it post to the server and check there for the OutageId. I just don’t like posting if it isn’t going to make a db call. I’d share a demo somewhere if I knew how. This is an internal application so my options are limited.
I found the following link that helps me grey out the readonly fields. jqGrid: How to grey out read only fields on add/edit form dialog?
But im looking for something that helps me grey out fields that are disabled.
Any thoughts on how i can get this to work?
Editing to add code to explain my situation better. All my examples below are using the gray out code found in the link above.
This first piece of code was working perfectly with the solution on the link above to gray out the readonly parts. But we had to change it to a selection list.
//
// This grays out the field name and the input field. (But this had to be changed to a selection list for business reasons)
//
//{ name: 'tCode', index: 'tCode', width: 63, align: "left", editable: true, editoptions: { maxlength: "25", readonly: istCodeReadOnly } },
This next piece of code grays out the selection but not the field name next to it.
// This grays out the selection but not the field name
{
name: 'tCode', index: 'tCode', width: 63, align: "left", editable: true, editrules: { required: true }, edittype: "select", editoptions: {
disabled: istCodeReadOnly,
async: false, dataUrl: '#Url.Action("GettCodes", "Home")',
buildSelect: function (result) {
var response = $.parseJSON(result);
var s = '<select>';
$.each(response, function () {
s += "<option value='" + this.code + "' > " + this.description + "</option>";
});
return s + "</select>";
}
}
},
This was the first attempt when nothing was grayed out. Its like the readonly field was never recognized. Basically nothing happens.
// This does not gray out the field name or the field itself
{
name: 'tCode', index: 'tCode', width: 63, align: "left", editable: true, editrules: { required: true }, edittype: "select", editoptions: {
readonly: istCodeReadOnly,
async: false, dataUrl: '#Url.Action("GettCodes", "Home")',
buildSelect: function (result) {
var response = $.parseJSON(result);
var s = '<select>';
$.each(response, function () {
s += "<option value='" + this.code + "' > " + this.description + "</option>";
});
return s + "</select>";
}
}
},
I just found JQGrid , and think that JQgrid is very mature and perfect to use with Web API
I have a few questions:
we are using Web Api and have the following HTML code and Controller.
The Image field loses its data when It comes back to the controller. Google debugger shows data for the image field on the HTML, but if I set a breakpoint on the Put method inside the controller, Visual Studio , I can see the product entity with all its fields filled with data, all but one; the image field is null.
It took me some digging to get this working , therefore I decided to share the HTML code + the WebApi controller it with the community.
1- am I am doing this right (Grid parameters) ?
2-Why the image fields comes back null ?
3-How can I implement a search ?
this will not get called
public dynamic GetProducts4JqGrid1(string sidx, string sord, int page, int rows, bool _search, string searchField, string searchOper, string searchString)
4-why i Must pass the Entity ID to the controller ? I tried many other ways and it always come back as "0" so must pass the Id to the Put method , is this the only way ?
JQGrid is awesome with Web Api
nice to have everything under one roof
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:jqgriddocs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using RoboMVC.Contracts;
using RoboMVC.Model;
namespace RoboMVC.Web.Controllers.jQgrid
{
public class ProductsJQgridController : ApiControllerBase
{
public ProductsJQgridController(IRoboMVCUow uow)
{
Uow = uow;
}
public dynamic GetProducts4JqGrid(string sidx, string sord, int page, int rows)
{
//var products = Uow.Product.GetAllProducts().OrderBy(e => e.ProductId) as IEnumerable<Product>;
var pageIndex = Convert.ToInt32(page) - 1;
var pageSize = rows;
var totalRecords = Uow.Product.Count();
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
var products = Uow.Product.GetAllProducts().OrderBy(e => e.ProductId).Skip(pageIndex * pageSize).Take(pageSize) as IEnumerable<Product>;
return new
{
total = totalPages,
page = page,
records = totalRecords,
rows =
(
from product in products
select new
{
id = product.ProductId,
cell = new object[]
{
product.ProductId,
product.Description,
product.SalePrice,
product.SaleCommissionFactor,
product.Stock,
product.StockMax,
product.StockMin,
product.DateOfEntry,
product.LastDateOfSale,
product.SKU,
product.LastCostPaid,
product.Weight,
product.Image,
product.Categoy,
}
}).ToList()
};
}
public HttpResponseMessage Put( int id, Product product)
{
product.ProductId = Convert.ToInt32(id);
Uow.Product.Update(product);
Uow.Commit();
var result = new HttpResponseMessage(HttpStatusCode.NoContent);
return result;
}
public HttpResponseMessage Post(int id, Product product)
{
product.ProductId = Convert.ToInt32(id);
product = Uow.Product.Add(product);
Uow.Commit();
var response = Request.CreateResponse<Product>(HttpStatusCode.Created, product);
string uri = Url.Route(null, new { id = product.ProductId });
response.Headers.Location = new Uri(Request.RequestUri, uri);
return response;
}
public HttpResponseMessage Delete(int id)
{
Uow.Product.Delete(id);
Uow.Commit();
var result = new HttpResponseMessage(HttpStatusCode.NoContent);
return result;
}
}
}
<script>
var API_URL = "/api/ProductsJQgrid/";
jQuery("#gridMain").jqGrid({
//http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options
url: "/api/ProductsJQgrid/GetProducts4JqGrid/",
datatype: 'json',
mtype: 'GET',
pager: '#pagernav',
viewrecords: true,
height: '60%',
width: '100%',
hoverrows: true,
rownumbers: true,
shrinkToFit: true,
gridview: true,
search: true,
ignoreCase:true,
loadonce: false,
viewsortcols: [false, "horizontal", true],
imgpath: '../../Content/jquery.jqGrid/content/images/',
rowNum: 10,
cache: true,
rowList: [10, 20, 30],
sortable: true,
sortname: 'productId',
sortorder: "desc",
// sorttype: "text",
caption: "CRUD With ASP.NET Web API",
autowidth: true,
colNames: ['productId', 'Description', 'SalePrice', 'SaleCommissionFactor', 'Stock', 'StockMax', 'StockMin', 'DateOfEntry', 'LastDateOfSale', 'SKU', 'LastCostPaid', 'Weight', '<image src=images/arrow-right.gif width=16 height=16>', 'Categoy'],
colModel: [
//http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
{ key:true, name: 'productId', index: 'productId', width: 40, search : true , sorttype: "int", editable: false },
{ name: 'description', index: 'description', editable: true, edittype: 'text', width: 70 },
{ name: 'salePrice', index: 'salePrice', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "float", formatter: "number" },
{ name: 'saleCommissionFactor', index: 'saleCommissionFactor', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "float", formatter: "number" },
{ name: 'stock', index: 'stock', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "int" },
{ name: 'stockMax', index: 'stockMax', editable: true, cellEdit:true, edittype: 'text', width: 50, align: "right", sorttype: "int"},
{ name: 'stockMin', index: 'stockMin', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "int"},
{ name: 'dateOfEntry', index: 'dateOfEntry', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "date", formatter: "date" },
{ name: 'lastDateOfSale', index: 'lastDateOfSale', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "date", formatter: "date" },
{ name: 'sKU', index: 'sKU', editable: true, edittype: 'text', width: 70 },
{ name: 'lastCostPaid', index: 'lastCostPaid', editable: true, edittype: 'text', width: 50, align: "right", sorttype: "float", formatter: "number" },
{ name: 'weight', index: 'weight', editable: true, edittype: 'text', width: 70 },
{ name: 'image', index: 'image', editable: false, search:false, width: 50, align: "right", },
{ name: 'categoy', index: 'categoy', editable: true, edittype: 'text', width: 70 }
],
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: true,
id: "id", // from the controller returned value
cell: "cell",
search: "_search"
},
subGrid: true
});
function updateDialog(action) {
return {
url: "/api/ProductsJQgrid/"
, closeAfterAdd: true
, closeAfterEdit: true
, afterShowForm: function (formId) { }
, modal: true
, onclickSubmit: function (params) {
var list = $("#gridMain");
var selectedRow = list.getGridParam("selrow");
var rowData = list.getRowData(selectedRow);
params.mtype = action;
params.url += rowData.productId;
debugger;
// image has the right data here
}
, width: "600"
};
}
jQuery("#gridMain")
.jqGrid('navGrid', '#pagernav',
{ add: true, edit: true, del: true, search: true,refresh: true },
updateDialog('Put'),
updateDialog('Post'),
updateDialog('Delete'),
{ sopt: ["cn"] } // Search options. Some options can be set on column level
)
// .filterToolbar({ autoSearch: false, searchOnEnter: false, stringResult: true })
;
$(window).bind('resize', function () {
jQuery("#gridMain").setGridWidth($('#parentDiv').width() - 30, true);
}).trigger('resize');
</script>
I have a jqGrid on a view page and it is loaded based on gathering data from a few select lists.
The first time through all is fine. If I change one of the select lists the .change function is triggered but the .jqGrid doesnt fire so the Controller method isnt hit.
My jqGrid code
$("#Builds").change(function () {
var programID = $("#ProgramID").val();
var buildID = $('#Builds').val();
$("#UpdateBuild").show();
// Set up the jquery grid
$("#jqTable").jqGrid({
// Ajax related configurations
url: '#Url.Action("_CustomBinding")',
datatype: "json",
mtype: "POST",
postData: {
programID: programID,
buildID: buildID
},
// Specify the column names
colNames: ["Assembly ID", "Assembly Name", "Cost", "Order", "Budget Report", "Partner Request", "Display"],
// Configure the columns
colModel: [
{ name: "AssemblyID", index: "AssemblyID", width: 40, align: "left", editable: false },
{ name: "AssemblyName", index: "AssemblyName", width: 100, align: "left", editable: false },
{ name: "AssemblyCost", index: "AssemblyCost", width: 40, align: "left", formatter: "currency", editable: true },
{ name: "AssemblyOrder", index: "AssemblyOrder", width: 30, align: "left", editable: true },
{ name: "AddToBudgetReport", index: "AddToBudgetReport", width: 40, align: "left", formatter: "checkbox", editable:true, edittype:'checkbox'},
{ name: "AddToPartnerRequest", index: "AddToPartnerRequest", width: 45, align: "left", formatter: "checkbox", editable:true, edittype:'checkbox'},
{ name: "Show", index: "Show", width: 20, align: "left", formatter: "checkbox", editable:true, edittype:'checkbox'}],
// Grid total width and height and formatting
width: 650,
height: 200,
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"
}).navGrid("#jqTablePager",
{ refresh: true, add: true, edit: true, del: true },
{}, // settings for edit
{}, // settings for add
{}, // settings for delete
{sopt: ["cn"]} // Search options. Some options can be set on column level
);
});
My controller Code:
[HttpPost]
public JsonResult _CustomBinding(string programID, string buildID, int page, int rows)
{
/* Variable Declarations */
BuildsRepository br = new BuildsRepository();
IEnumerable<ProgramsAssemblyBuilds> pab = br.GetProgramAssembliesBuilds(Convert.ToInt32(programID), Convert.ToInt32(buildID));
// Calculate the total number of pages
var totalRecords = pab.Count();
var totalPages = (int)Math.Ceiling((double)totalRecords / (double)rows);
var data = (from s in pab
select new
{
AssemblyID = s.AssemblyID,
cell = new object[] { s.AssemblyID, s.AssemblyName, s.AssemblyCost, s.AssemblyOrder, s.AddToBudgetReport, s.AddToPartnerRequest, s.Show}
}).ToArray();
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = data.Skip((page - 1) * rows).Take(rows)
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
Anyone have any ideas on this one?
Thanks
You should create the grid only once. So you should place the code
$("#jqTable").jqGrid({ ... });
outside of the change event handler.
To reload the grid you should use
$("#Builds").change(function () {
$("#jqTable").trigger("reloadGrid", [{page: 1}]);
$("#UpdateBuild").show();
});
At the end to have actual values from "#ProgramID" and '#Builds' you should use functions (methods) as the programID and buildID properties of postData:
// Set up the jquery grid
$("#jqTable").jqGrid({
// Ajax related configurations
url: '#Url.Action("_CustomBinding")',
datatype: "json",
mtype: "POST",
postData: {
programID: function() { return $("#ProgramID").val(); },
buildID: function() { return $('#Builds').val(); }
},
...
});
See more information here.
I need help display data in the jqGrid footer row. This is my configuration on the Server. Notice the userdata = (Hours) line.
// Format the data for the jqGrid
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = (
from a in activities
select new
{
id = a.ActivityId,
cell = new string[] {
a.ActivityId.ToString(),
DateTime.Parse(a.Date.ToString()).ToShortDateString(),
a.Person.Name.ToString(),
a.ActivityName.ToString(),
a.Hours.ToString()
}
}).ToArray(),
userdata = (Hours)
};
// Return the result in json
return Json(jsonData, JsonRequestBehavior.AllowGet);
The userData amount that I need displayed in the footer is coming through in the JSON. I am using Fiddler to view it. Here is a screenshot of the fiddler view:
alt text http://shirey.technologyblends.com/Content/images/json.jpg
I need to display this value of "12" in the footer. This the HTML I am using to read the JSON:
jQuery("#list").jqGrid({
url: gridDataUrl + '?startDate=' + startDate.toJSONString() + '&endDate=' + endDate.toJSONString(),
datatype: "json",
mtype: 'GET',
colNames: ['Activity ID', 'Date', 'Employee Name', 'Activity', 'Hours'],
colModel: [
{ name: 'ActivityId', index: 'ActivityId', width: 40, align: 'left' },
{ name: 'Date', index: 'Date', width: 50, align: 'left' },
{ name: 'Person.Name', index: 'Person.Name', width: 100, align: 'left', resizable: true },
{ name: 'ActivityName', index: 'ActivityName', width: 100, align: 'left', resizable: true },
{ name: 'Hours', index: 'Hours', width: 40, align: 'left' }
],
loadtext: 'Loading Activities...',
multiselect: true,
rowNum: 20,
rowList: [10, 20, 30],
imgpath: gridimgpath,
height: 'auto',
width: '700',
pager: jQuery('#pager'),
sortname: 'ActivityId',
viewrecords: true,
sortorder: "desc",
caption: "Activities",
footerrow: true, userDataOnFooter: true, altRows: true
}).navGrid('#pager', { search: true, edit: false, add: false, del: false, searchtext: "Search Activities" });
Try to use following
var jsonData = new {
total = totalPages,
page = page,
records = totalRecords,
rows = (
from a in activities
select new {
id = a.ActivityId,
cell = new string[] {
a.ActivityId.ToString(),
DateTime.Parse(a.Date.ToString()).ToShortDateString(),
a.Person.Name.ToString(),
a.ActivityName.ToString(),
a.Hours.ToString()
}
}).ToArray(),
userdata = new {
Hours = 12
}
};
then the userdata part of the JSON data will be
"userdata":{"Hours":12}
which follows to displaying of the bold value 12 in the column Hours of the footer part of the jqGrid table.