JQGrid and MVC Full Working Example - asp.net-mvc

I would like to use JQ grid in my current MVC project but I'm running into quite a few problems trying to figure it out. I find the available documentation lacking if not missing and all the problems seem to focus on a single aspect such as getting data into the grid. Well I'm way beyond that point and I would love to see a fully functional example that does fetching data, sorting, paging, add, edit, delete and search all in one with MVC. Is there such an example anywhere on the web?
Furthermore I would like to know if I can use data annotations in conjunction with JQ grid add/edit? From what I read so far it seems that I have to define new validation rules within JQ Grid declaration and that rules that I established on the model are being ignored. Is there a way to use model rules during JQ Grid CRUD operations? I was thinking along the way of making my own jquery dialog popup with appropriate partial view loaded once a row is selected and add/edit button is clicked. however I cannot find JQ grid event which is raised when Add button is clicked. It seems to force you into using their auto generated modal popup form...
I'm not sure if all this makes any sense to any of you but any help would be appreciated. If anyone has a link to all JQ Grid events even that would be a big help... Thanks!

I just tested JQGrid and DataAnnotations on my underlying datasource and there does not appear to be any support (yet hopefully) for them.
As for the for the MVC part, are you looking to use the ASP.NET MVC Helpers provided by trirand.net? if so you can find a working example here:
http://www.trirand.net/aspnetmvc/grid/editrowinlineactionicons
-Brandon

you can try my Jq.Grid
already support for data annotation and simple searching

Razor View: Total CRUD Operation
#{
ViewBag.Title = "Home Page";
}
<table id="tbl"></table>
<div id="pager"></div>
#section scripts{
<link href="~/Content/Theme/ui.jqgrid.css" rel="stylesheet" />
<link href="~/Content/Theme/jquery-ui.min.css" rel="stylesheet" />
<script src="~/Scripts/jqGrid/jquery.jqGrid.js"></script>
<script src="~/Scripts/jqGrid/grid.inlinedit.js"></script>
<script src="~/Scripts/jqGrid/grid.locale-en.js"></script>
<script src="~/Scripts/jqGrid/jquery.sortable.js"></script>
<script>
$(function () {
var lastsel;
$("#tbl").jqGrid({
url: "/Home/GetData",
mtype: "Get",
datatype: "Json",
colNames: ["ID", "Name", "Address", "Mobile", "Salary"],
colModel: [
{ name: 'id', index: 'id', editable: false, align: 'center' },
{ name: 'name', index: 'name', editable: true },
{ name: 'address', index: 'address', editable: true },
{ name: 'mobile', index: 'mobile', editable: true },
{ name: 'salary', index: 'salary', editable: true }
],
loadonce: true,
pager: "#pager",
rowNum: 20,
height:"100%",
onSelectRow: function (id) {
if (id && id !== lastsel) {
$("#tbl").restoreRow(lastsel);
$("#tbl").editRow(id, true);
lastsel = id;
}
},
caption: "jqGrid",
editurl: "/Home/EditData",
viewrecords: true,
sortorder: "desc",
sortname: "id",
}).navGrid("#pager", { edit: false, add: false, del: true, refresh: false, search: false },
{},
{},
{
url: "/Home/DelData",
mtype: "Post",
delData: "row_id_s",
}).inlineNav("#pager", {
add: true,
addParams: {
addRowParams: {
url: "/Home/AddData",
mtype: "Post"
}
}
});
});
</script>
}
MVC Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using jqGrid_Exam2.Models;
using System.Data.Entity;
namespace jqGrid_Exam2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult GetData()
{
DBcontext db = new DBcontext();
var data = db.EmployeeTbls.ToList<EmployeeTbl>();
return Json(data,JsonRequestBehavior.AllowGet);
}
[HttpPost]
public void EditData(EmployeeTbl emp)
{
DBcontext db = new DBcontext();
db.Entry(emp).State = EntityState.Modified;
db.SaveChanges();
}
[HttpPost]
public void AddData(EmployeeTbl emp)
{
DBcontext db = new DBcontext();
db.EmployeeTbls.Add(emp);
db.SaveChanges();
}
[HttpPost]
public void DelData(string id)
{
DBcontext db = new DBcontext();
EmployeeTbl emp = db.EmployeeTbls.Find(int.Parse(id));
db.EmployeeTbls.Remove(emp);
db.SaveChanges();
}
}
}

Related

ASP.NET MVC 5: Client Validation is not working for a view model (annotations) [duplicate]

I have JQuery popups and i want to put required field validations on it and for this i have set required attributes in model and have also set the validation message for them in the view but that required field validations are not working on popups. Required field validation is working fine on forms other than JQuery Popups....Please guide me that what should i do to tackle this issue...Following is my code.
Model
[Display(Name = "Material Code")]
[Required(ErrorMessage = "*")]
public string MaterialCode { get; set; }
View
<li>
#Html.LabelFor(m => m.MaterialCode)
#Html.TextBoxFor(m => m.MaterialCode)
#Html.HiddenFor(m => m.MaterialCodeId)
</li>
and following is my cod eto open a JQuery popup.
$('#btnAddCharge').on('click', function (event) {
event.preventDefault();
var actionURL = '#Url.Action("Edit", "Charges", new { Id = 0, #ticketId = #TicketId, UserId = UserId })';
$(dialogBox).dialog({
autoOpen: false,
resizable: false,
title: 'Edit',
modal: true,
show: "blind",
width: 'auto',
hide: "blind",
open: function (event, ui) {
$(this).load(actionURL, function (html) {
$('form', html).submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (res) {
if (res.success) {
$(dialogBox).dialog('close');
}
}
});
return false;
});
});
}
});
$(dialogBox).dialog('open');
});
The validator is parsed when the page is initially loaded. When you add dynamic content you need to reparse the validator. Modify your script to include the following lines after the content is loaded
$(this).load(actionURL, function (html) {
// Reparse the validator
var form = $('form');
form.data('validator', null);
$.validator.unobtrusive.parse(form);
$('form', html).submit(function () {
....
Side note: The code you have shown does not include #Html.ValidationMessageFor(m => m.MaterialCode) but I assume this is included.

Error during database connection with jqgrid

I'm trying to connect to database from jqgrid. I have this bug in the controller, does anyone know how to fix it?
Component LINQ to Entities does not recognize the method 'System.String ToString () "and you can not translate it to express the warehouse.
When given data rigidly works.
new {id = 1, cell = new[] {"1", "zzzzzz", "xxxxxx"}}
In addition, I would like to ask how to add edit to jqgrid?
View
<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:content contentplaceholderid="HeadContent" runat="server">
<link href="/Content/jquery-ui-1.8.7.css" rel="stylesheet" type="text/css" />
<link href="/Content/ui.jqgrid.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="/Scripts/js/i18n/grid.locale-en.js" type="text/javascript"></script>
<script src="/Scripts/jquery.jqGrid.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$("#list").jqGrid({
url: '/Home/LinqGridData/',
datatype: 'json',
mtype: 'GET',
colNames: ['CatID', 'CatName', 'Age'],
colModel: [
{ name: 'CatID', index: 'CatID', width: 40, align: 'left' },
{ name: 'CatName', index: 'CatName', width: 40, editable: true, align: 'left' },
{ name: 'Age', index: 'Age', width: 400, align: 'left' }],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
imgpath: '/scripts/themes/coffee/images',
caption: 'My first grid'
});
jQuery("#list").jqGrid('navGrid', "#pager", { edit: true, add: true, del: true });
jQuery("#list").jqGrid('inlineNav', "#pager");
});
</script>
</asp:content>
<asp:content contentplaceholderid="MainContent" runat="server">
<h2>My Grid Data</h2>
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div id="pager" class="scroll" style="text-align:center;"></div>
</asp:content>
Model
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace MvcApplication2.Models
{
public class Cat
{
[Key]
public int CatID { get; set; }
public string CatName { get; set; }
public string Age { get; set; }
}
}
Controller
public ActionResult LinqGridData(string sidx, string sord, int page, int rows)
{
var context = new CatEntities();
var jsonData = new
{
total = 1, //todo: calculate
page = page,
records = context.Cats.Count(),
rows = (
from question in context.Cats
select new
{
i = question.CatID,
cell = new string[] { question.CatID.ToString(), question.CatName, question.Age }
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
I think it's because the question for a moment it is sent to the database,
You can't send this:
question.CatID.ToString()
to SQL Server because it doesn't know what to do with the method call. If you force enumeration of the set first you can make use of .NET methods in memory:
from question in context.Cats.ToList()
The problem is going to be balancing performance. If the Cats unfiltered set is large performance will suffer as the entire table is loaded into memory. In your case you probably won't notice a difference as you're invoking ToArray() later anyway.
If possible, use Skip() and Take() to implement paging and keep your sets small.
You should also consider storing the result in a variable so that you can reference it for your rows and records properties rather than hitting the context twice.

Auto-complete doesn't work as expected

I tried to implement this in MVC 5 with jquery ui 1.10.2
#{
ViewBag.Title = "Home Page";
Layout = null;
}
<p>
Enter country name #Html.TextBox("Country")
<input type="submit" id="GetCustomers" value="Submit" />
</p>
<span id="rData"></span>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui.js"></script>
#Styles.Render("~/Content/themes/base/css")
<script type="text/javascript">
$(document).ready(function () {
$("#Country").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/AutoCompleteCountry",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function(data) {
response($.map(data, function(item) {
return { label: item.Country, value: item.Country };
}));
}
});
}
});
})
</script>
the server side is
...
[HttpPost]
public JsonResult AutoCompleteCountry(string term)
{
// just something to return..
var list = new List<string>() { "option1", "option2", "option3"};
var result = (from r in list
select r);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
I have two issues
1. it open up drop down autocomplete with 3 dots but without the actual strings.
2. It has this annoying message of "3 results were found" - I'd like to eliminate it..
DO you have any idea how to face those two issues or neater way to implement it in MVC5?
The 3 bullet points and "3 results were found" is because you are missing the jQuery UI css file. That file will format a drop down that will look a lot better. You can customize how the dropdown looks with additional css.
Also, you are seeing 3 empty results because your JS is referencing item.Country ...
return { label: item.Country, value: item.Country };
But your server code is just sending 3 strings.
new List<string>() { "option1", "option2", "option3"};
To fix, change your JS to just reference the item (the string) ...
return { label: item, value: item};
OR, change your server code to send more complex objects
new List<Object>() { new { Country = "option1" }, new { Country = "option2" }, new { Country = "option3" } };
use return data in place of return { label: item.Country, value: item.Country };

Passing Data from Controller to View using Ajax to filter results

I'm attempting to filter my results based on a drop down selected value. All the filtering and everything is working, I'm just struggling to get my view to update with the results. I'm leaving out some brackets and other irrelevant code Here is what I have:
public ViewResult Index()
{
-- this effectively returns all Invoices no matter what date --
var data = new UserBAL().GetInvoice(date);
return View(data);
}
My Jquery and Ajax is :
$(document).ready(function () {
$("[name='DDLItems']").change(function () {
var selection = $("[name='DDLItems']").val();
var dataToSend = {
//variable to hold selection?
idDate: selection
};
$.ajax({
type: "POST",
url: "Invoice/FilterInvoice",
data: dataToSend,
success: function (data) {
$("#Index").html(data);
}
[HttpPost] // Selected DDL value
public ActionResult FilterInvoice(int idDate)
{
switch (idDate)
{
case 0:
date = DateTime.Parse("01-01-1754");
break;
case 3:
date = DateTime.Now.AddMonths(-12);
break;
}
//var data is returning my expected results
var data = new UserBAL().GetInvoice(date);
// I know this isn't right and needs to be changed
return View(data);
My ajax success function isn't doing anything either So it i'm guessing this needs some tweaking. Also Here's how I am displaying the table using table tags. Keep in mind I left some code out but everything important is here, and the only issue is rendering my filtered results back to the view,
#foreach (var item in Model) {
<tr><td>
#Html.DisplayFor(modelItem => item.Invoice_Number)
#Html.DisplayFor(modelItem => item.Amt_Total)
</td>
Instead of passing view you can return the partial view as string then in ajax success using jquery you can update the result :
Controller Logic:
[HttpPost]
public JsonResult FilterInvoice(int idDate)
{
.....
return Json((RenderRazorViewToString("YourViewName", data)), JsonRequestBehavior.AllowGet);
}
[NonAction]
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Ajax call :
$.ajax({
//........
success: function (result) {
$("#Index").replaceWith(result);
}
});
Here's the answer if anyone else comes across this. This is what I ended up doing, the rows are getting filtered passed on the date parameter I'm passing to the URL of the function. Having the Grid populate inside the Ajax call also seemed like it was a problem so I had to take it out.
public JsonResult JqGrid(int idDate)
{
switch (idDate)
#region switch date
--Switch Statement--
#endregion
var invoices = new UserBAL().GetInvoice(date);
return Json(invoices, JsonRequestBehavior.AllowGet);
}
[HttpPost] // pretty much does nothing, used as a middle man for ajax call
public JsonResult JqGridz(int idDate)
{
switch (idDate)
#region switch date
--Switch Statement--
#endregion
var invoices = new UserBAL().GetInvoice(date);
return Json(invoices, JsonRequestBehavior.AllowGet);
}
Yes these two functions seem very redundant and they are. I don't know why my post wouldn't update data, but I needed to reload the grid each time and when I did that it would call the first function. So yea the post jqGridz is kinda of just a middle man.
Here's the jquery code I used
var dropdown
var Url = '/Invoice/JqGrid/?idDate=0'
$(document).ready(function () {
$("#jqgrid").jqGrid({
url: Url,
datatype: 'json',
mtype: 'GET', //insert data from the data object we created above
width: 500,
colNames: ['ID','Invoice #', 'Total Amount', 'Amount Due', 'Amount Paid', 'Due Date'], //define column names
colModel: [
{ name: 'InvoiceID', index: 'Invoice_Number', key: true, hidden: true, width: 50, align: 'left' },
{ name: 'Invoice_Number', index: 'Invoice_Number', width: 50, align: 'left'},
{ name: 'Amt_Total', index: 'Amt_Total', width: 50, align: 'left' },
{ name: 'Amt_Due', index: 'Amt_Due', width: 50, align: 'left' },
{ name: 'Amt_Paid', index: 'Amt_Paid', width: 50, align: 'left' },
{ name: 'Due_Date', index: 'Due_Date', formatter: "date", formatoptions: { "srcformat": "Y-m-d", newformat: "m/d/Y" }, width: 50, align: 'left' },
],
pager: jQuery('#pager'),
sortname: 'Invoice_Number',
viewrecords: false,
editable: true,
sortorder: "asc",
caption: "Invoices",
});
$("[name='DDLItems']").change(function () {
var selection = $(this).val();
dropdown = {
//holds selected value
idDate: selection
};
$.ajax({
type: "POST",
url: "Invoice/JqGridz",
data: dropdown,
async: false,
cache: false,
success: function (data) {
$("#jqgrid").setGridParam({ url: Url + selection})
$("#jqgrid").trigger('reloadGrid');
}
})
})
});

Display my data in jqGrid

In an ASP.NET MVC application using for the first time jqGrid.
I have a menu, I call "employee" from the menu in the master page like this :
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$(".mnuEmployee").click(function() {
$.post("/Employee/Index", null, function(data) {
$("#text").html(data);
});
});
});
</script>
In the controller, I have this :
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index()
{
EmployeeModel model = new EmployeeModel();
model.List = _employeeService.List();
model.Languages = _languageService.List();
return View("Index", model);
}
In the View (Index.ascx), I have this :
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#sandgrid").jqGrid({
url: '/Employee/MyGridData/',
datatype: 'json',
mtype: 'GET',
height: 255,
width: 600,
colNames: ['Index', 'Name', 'Code'],
colModel: [
{ name: 'item_id', index: 'item_id', width: 65 },
{ name: 'item', index: 'item', width: 150 },
{ name: 'item_cd', index: 'item_cd', width: 100}],
pager: jQuery('#sandgridp'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'item_id',
sortorder: "desc",
viewrecords: true,
caption: 'Liste des employés'
});
});
</script>
<table id="sandgrid" cellpadding="0" cellspacing="0"></table>
<div id="sandgridp" style="text-align:center;"></div>
The problem is in this last part (I think), I have all datas in my model, I'd like display employee list in a jqGrid and languages (and more are coming) in classic textbox, textarea, ... How can I use the "model.List" (IList) to show in the grid ?
Thanks,
What is the reason to show languages in textbox/textarea? Did you mean select? If so then look at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:common_rules, for the "select" edit type. Note that you can have multiselect list.
If you just want to display languages, then do this in your model:
model.Languages = string.Join(_languageService.List().Select(x => x.Name).ToArray(), ",");
And then jqGrid will display your languages as a string, comma-separated.
But I'd suggest you to decide (since it's not clear from the Q):
how you want to display languages/list
do you want to edit them and how
Also take a look at custom formatters http://www.trirand.com/jqgridwiki/doku.php?id=wiki:custom_formatter, you can write a function to convert your languages list into anything you want, on input you get data, on output you return string with any HTML. Don't forget "unformatter" if you need to edit the cell value. For example, I use custom formatter to display checkbox images instead of true/false text.
I'm a little confused. You have your jqGrid set up to do an AJAX query for it's data as JSON so there's no need to include in in the Index view's model.
url: '/Employee/MyGridData/',
datatype: 'json',
To use the AJAX method your controller needs a MyGridData action.
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult MyGridData ()
{
var list = _employeeService.List();
return Json(list);
}
Also, the name and index properties in the colModel must match the property names in your model.

Resources