implementing jTable MVC 4 - asp.net-mvc-4

I have following
****** controller ***********
namespace DLM.Controllers{
public class BooksController : Controller
{
private IRepositoryContainer _repository;
//
// GET: /Books/
public ActionResult Index()
{
return View();
}
[HttpPost]
public JsonResult ListBooks(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
try
{
//Get data from database
int bookCount = _repository.BookRepository.GetBooksCount();
List<Books> book = _repository.BookRepository.GetBooks(jtStartIndex, jtPageSize, jtSorting);
//Return result to jTable
return Json(new { Result = "OK", Records = book, TotalRecordCount = bookCount });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
***** ListBooks View ************
{
#Styles.Render("~/Scripts/jtable/jtable.2.3.0/themes/metro/darkgray/jtable.min.css")
<script src="/Scripts/jtable/jtable.2.3.0/jquery.jtable.min.js" type="text/javascript"></script>
<div id="BookTableContainer"></div>
<script type="text/javascript">
$(document).ready(function () {
$('#BookTableContainer').jtable({
title: 'The Student List',
paging: true, //Enable paging
pageSize: 10, //Set page size (default: 10)
sorting: true, //Enable sorting
defaultSorting: 'Book Title ASC', //Set default sorting
actions: {
listAction: '/Books/Index',
deleteAction: '/Books/DeleteBook',
updateAction: '/Books/UpdateBook',
createAction: '/Books/AddBook'
},
fields: {
BooksID: {
key: true,
create: false,
edit: false,
list: false
},
Code_No: {
title: 'Book Code',
width: '23%'
},
Title: {
title: 'Book Title',
list: false
},
Author: {
title: 'Author',
list: false
},
Page_No: {
title: 'Number of Pages',
width: '13%'
},
Y_of_P: {
title: 'Year of Publication',
width: '12%'
},
Language: {
title: 'Language',
width: '15%'
},
Subject: {
title: 'Subject',
list: false
},
Publisher: {
title: 'Publisher',
list: false
},
Keyword: {
title: 'Keywords',
type: 'textarea',
width: '12%',
sorting: false
}
}
});
//Load student list from server
$('#BookTableContainer').jtable('load');
});
</script>
}
ISSUE *****************
When I am trying to access /Books/ListBooks
There is an error The resource cannot be found.
Please help me out i am new to jTable and it's implementation.

Use ListBooks action instead of Index action in jtable listAction. Index action will be used to render the view and after the jquery will load the data from ListBooks

I think you are requesting /Books/Listbooks through browser URL. Browser by default uses get method to get data from server and you putted HttpPost DataAnnotation over the method thats why you are getting error so if you want output makes following two changes.
1)Remove HttpPost Data Annotation of ListBooks Method.
2)Add JsonRequestBehavior.AllowGet in return Json method as follows
return Json(new { Result = "OK", Records = book, TotalRecordCount = bookCount }, JsonRequestBehavior.AllowGet )
Now Your method will work Perfectly.

Related

How to create location select box in cshtml page without model

I want to create a select box for the location field, in which if one types any letter should call API and fetch location details in the dropdown
I tried the below code but didn't work
<select class="js-data-example-ajax form-control" id="FilterLocation"></select>
#Html.Hidden("FilterLocation", new { id = "locationId" })
In the script written below code
function setLocation() {
$('.js-data-example-ajax').select2({
ajax: {
type: 'PUT',
url: function (params) {
return '/api/GoogleCustomSearch/getLocation?matchingName=' + params.term
},
delay: 250,
data: function (params) {
var query = {
}
// Query paramters will be ?search=[term]&page=[page]
return query;
},
processResults: function (data) {
data = JSON.parse(data);
let results = []
if (data.location !== null) {
data.location.forEach((e) => {
results.push({
id: e,
text: e
})
})
}
return {
results: results
};
}
},
placeholder: "Search"
})
$('.js-data-example-ajax').on('change',function(e){
var selVal = $('#FilterLocation').val()
$('#locationId').val(selVal)
//getZipCodeForDynamic(selVal)
})
var $newOption = $("<option selected='selected'></option>")
$("#FilterLocation").append($newOption).trigger('change');
}
Dropdown options are not getting with above code.
Here is a working demo for select2:
View:
<select id="mySelect2" class="js-data-example-ajax" style="width:200px"></select>
js:
$('#mySelect2').select2({
ajax: {
type: 'PUT',
url: "GetSelect2Data",
delay: 250,
data: function(params) {
var query = {
search: params.term,
}
// Query parameters will be ?search=[term]
return query;
},
processResults: function(data) {
//data = JSON.parse(data);
let results = []
if (data.location !== null) {
data.location.forEach((e) => {
results.push({
id: e,
text: e
})
})
}
return {
results: results
};
}
},
placeholder: "Search"
});
model:
public class Select2Model {
public List<string> Location { get; set; }
}
action:
[HttpPut]
public ActionResult GetSelect2Data(string Search)
{
return Json(new Select2Model() { Location = new List<string> { "a"+Search,"b" + Search, "c" + Search } });
}
result:

KendoUI SignalR grid not update if data is posed via ajax in my ASP.NET Core 5 web application

I have a KendoUI grid which uses SignalR. Whilst the grid itself works fine if you update the data inline or incell, it doesn't work if I update the data in a form which uses ajax to post it to my controller.
It was my understanding that, if I injected my hub into my controller and then called (whichever I needed, create, update or destroy) :
await _fixtureHub.Clients.All.SendAsync("update", model);
or
await _fixtureHub.Clients.All.SendAsync("update", model);
That it would tell the clients that the data had been changed/created and the grid would update to reflect that change. This isn't happening however and I'm wondering what I've done wrong or missing.
To start, here is my signalR bound grid.
$('#fixture_grid').kendoGrid({
dataSource: {
schema: {
model: {
id: "Id",
fields: {
Created_Date: {
type: "date"
},
Commencement_Date: {
type: "date"
}
}
}
},
type: "signalr",
autoSync: true,
transport: {
signalr: {
promise: fixture_hub_start,
hub: fixture_hub,
server: {
read: "read",
update: "update",
create: "create",
destroy: "destroy"
},
client: {
read: "read",
update: "update",
create: "create",
destroy: "destroy"
}
}
}
},
autoBind: true,
sortable: true,
editable: false,
scrollable: true,
columns: [
{
field: "Created_Date",
title: "Created",
format: "{0:dd/MM/yyyy}"
},
{
field: "Commencement_Date",
title: "Commencement",
format: "{0:dd/MM/yyyy}"
},
{
field: "Charterer",
template: "#if(Charterer !=null){# #=Charterer_Name# #} else { #--# }#"
},
{
field: "Region",
template: "#if(Region !=null){# #=Region_Name# #} else { #--# }#"
}
]
});
Here is the relative hub for that grid:
var fixture_url = "/fixtureHub";
var fixture_hub = new signalR.HubConnectionBuilder().withUrl(fixture_url, {
transport: signalR.HttpTransportType.LongPolling
}).build();
var fixture_hub_start = fixture_hub.start({
json: true
});
Here is the KendoUI wizard with form integration which I update the grid with, this form can process either a creation or an update data, this is achieved by checking the Id that is passed in. Whereby 0 equals new and >0 is existing.
function wizard_fixture() {
let wizard_name = "#wizard-fixture";
//Load Wizard
$(wizard_name).kendoWizard({
pager: true,
loadOnDemand: true,
reloadOnSelect: false,
contentPosition: "right",
validateForms: true,
deferred: true,
actionBar: true,
stepper: {
indicator: true,
label: true,
linear: true
},
steps: [
{
title: "Step 01",
buttons: [
{
name: "custom",
text: "Save & Continue",
click: function () {
let wizard = $(wizard_name).data("kendoWizard");
var validatable = $(wizard_name).kendoValidator().data("kendoValidator");
if (validatable.validate()) {
$.ajax({
type: "POST",
traditional: true,
url: "/Home/Process_Fixture",
data: $(wizard_name).serialize(),
success: function (result) {
...do stuff
},
error: function (xhr, status, error) {
console.log("error")
}
});
}
}
}
],
form: {
formData: {
Id: fixtureviewmodel.Id,
Created_User: fixtureviewmodel.Created_User,
Created_Date: fixtureviewmodel.Created_Date,
Connected: fixtureviewmodel.Connected
},
items: [
{
field: "Fixture_Id",
label: "Id",
editor: "<input type='text' name='Id' id='Fixture_Id' /> "
},
{
field: "Created_User",
label: "Created user",
editor: "<input type='text' name='Created_User' id='Created_User_Fixture' />"
},
{
field: "Created_Date",
id: 'Created_Date_Fixture',
label: "Created date",
editor: "DatePicker",
}
]
}
},
],
});
I've shortened this to demonstrate the custom button and the ajax posting that happens to Process_Fixture. Here is my controller which handles that:
public async Task<JsonResult> Process_Fixture(Fixture model)
{
if (model.Id == 0)
{
if (ModelState.IsValid)
{
var fixture = await _fixture.CreateAsync(model);
Update connected clients
await _fixtureHub.Clients.All.SendAsync("create", model);
return Json(new { success = true, data = fixture.Id, operation = "create" });
}
return Json(new { success = false });
}
else
{
var fixture = await _fixture.UpdateAsync(model);
await _fixtureHub.Clients.All.SendAsync("update", model);
return Json(new { success = true, data = fixture.Id, operation = "update" });
}
}
As you can see, I have injected my hub and I have called the "create" message to it which I believed would force the grid to update with whatever had changed or been created.
Here is the hub itself:
public class FixtureHub : DynamicHub
{
private readonly IRepository<Fixture> _fixtures;
private readonly IRepository<ViewGridFixtures> _viewFixtures;
public FixtureHub(IRepository<Fixture> fixtures, IRepository<ViewGridFixtures> viewFixtures)
{
_fixtures = fixtures;
_viewFixtures = viewFixtures;
}
public override Task OnConnectedAsync()
{
Groups.AddToGroupAsync(Context.ConnectionId, GetGroupName());
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception e)
{
Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupName());
return base.OnDisconnectedAsync(e);
}
public class ReadRequestData
{
public int ViewId { get; set; }
}
public IQueryable<ViewGridFixtures> Read()
{
IQueryable<ViewGridFixtures> data = _viewFixtures.GetAll();
return data;
}
public string GetGroupName()
{
return GetRemoteIpAddress();
}
public string GetRemoteIpAddress()
{
return Context.GetHttpContext()?.Connection.RemoteIpAddress.ToString();
}
}
I need some help here in understanding how I can tell the hub that the update/create/destroy has been called and it needs to do something. At the moment, I feel like injecting the hub and then calling the clients.all.async isn't the right way. With ajax it seems to ignore it and I wonder if the two technologies are working against each other.

not able to display records as per page size in kendo grid

i want to perform filtering,sorting and no of records in kendo grid but it is not working.
this is my view page:
<script>
$(document).ready(function () {
$("#categories-grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "#Html.Raw(Url.Action("categoriesList", "Admin"))",
type: "POST",
dataType: "json",
data: '',
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
error: function(e) {
display_kendoui_grid_error(e);
// Cancel the changes
this.cancelChanges();
},
pageSize: 2,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
pageable: {
refresh: true,
pageSizes: [10,20,30]
},
editable: {
confirmation: false,
mode: "inline"
},
scrollable: false,
columns: [{
field: "CategoryName",
title: "CategoryName",
width: 100
}, {
field: "CategoryId",
title: "Edit",
width: 100,
template: 'Edit'
}]
});
});
</script>
This is my controller side http post action:
[HttpPost]
public ActionResult categoriesList(DataSourceRequest command)
{
Categories categoriesBal = new Categories();
List<CategoryModel> categoriesList = new List<CategoryModel>();
var category = GetCategory();
ViewBag.Category = GetCategory();
List<Category> categoryDetails = categoriesBal.fetchCategory();//here i am fetching categoryid,name
var gridModel = new DataSourceResult
{
Data = categoryDetails.Select(x =>
{
var categoryModel = new CategoryModel();
categoryModel.CategoryId = x.CategoryId;
categoryModel.CategoryName = x.Name;
return categoryModel;
}),
Total = categoryDetails.Count
};
return Json(gridModel);
}
This is my DataSourceRequest class
public class DataSourceRequest
{
public int Page { get; set; }
public int PageSize { get; set; }
public DataSourceRequest()
{
this.Page = 1;
this.PageSize = 10;
}
}
This is my Category model:
public class CategoryModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public int frequency { get; set; }
public virtual ICollection<SubcategoryModel> subCategory { get; set; }
}
i am having 12 category.when i am setting item per page dat is 2 it display all records.
can any body tell me what is the problem in my code and how to perform sorting and filtering??
Change your schema to act as a function
schema: {
data: function(response) {
return response.Data ;
}
total: function(response) {
return response.Total;
}
},
and pageable to
pageable: {
refresh: true,
pageSizes: [2,10,20,30]
},
and do not see the use of DataSourceRequest in your code since you don't send the pageSize from the read . send a object of DataSourceRequest and return only what is specify in your DataSourceRequest . in this case only two records
transport: {
read: function (options) {
var commandOBJ=[{
Page: 1, // Once the first two item is loaded and you click for the next page you will have the page in "options" (should be like options.page)
PageSize:2
}];
$.ajax({
url:"#Html.Raw(Url.Action("categoriesList", "Admin"))",
data: { command: bookmarkID },
dataType: "json",
cache: false,
success: function (result) {
options.success(result);
},
error: function (result) {
options.error(result);
}
});
}
}
Now from your action categoriesList check the command and send data accordingly . and your read action can be a GET instead of POST . hope this Helps
Instead of using your custom DataSourceRequest class, use the KendoGridMvcRequest class from this project, this class correctly maps the paging, sorting and filtering.
Also available as nuget.
See this link for demo.

jqGrid url not getting called with server side paging & sorting & postData: Form.searialize() in MVC 4

I am implementing server side paging & sorting for jqGrid in MVC 4. I am passing view model object as postData to jqGrid url action method. have a look at grid definition.
var isGridDefined = false;
$(document).ready(function () {
function DefineGrid(Year, Month) {
var mygrid = $("#RptUpload");
mygrid.jqGrid({
loadonce: false,
async: false,
datatype: 'json',
postData: { bReload: true, Year: Year, Month: Month },
url: '#Url.Action("DMEUploadDetailsList", "Reports")',
jsonReader: { repeatitems: false, root: "DataRows" },
colNames: ['#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_OrderID',
'#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_CompanyName',
'#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientID',
'#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientName',
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_DOB",
'#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Insurance',
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_UploadDate"
],
colModel: [
{ name: 'ReadingID', index: 'ReadingID', width: 55, fixed: true, sorttype: 'integer', align: 'center' },
{
name: 'CompanyName', index: 'CompanyName', align: 'center', width: 200,
cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' },
},
{ name: 'PatientID', index: 'PatientID', width: 55, fixed: true, sorttype: 'integer', align: 'center' },
{
name: 'PatientName', index: 'PatientName', align: 'center', width: 200,
cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' },
},
{
name: 'DOB', index: 'DOB', width: 80, fixed: true, sorttype: 'date', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' },
align: 'center'
},
{ name: 'InsuranceType', index: 'InsuranceType', align: 'center', width: 150, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' }, },
{
name: 'UploadDate', index: 'UploadDate', width: 80, fixed: true, sorttype: 'date', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' },
align: 'center'
}
],
rowNum: 20,
rowList: [20, 50, 100, 200],
pager: '#UploadPager',
caption: '#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Title',
viewrecords: true,
height: 'auto',
width: 770,
hidegrid: false,
shrinkToFit: true,
scrollOffset: 0,
headertitles: true,
loadError: function (xhr, status, error) {
alert(status + " " + error);
},
//onPaging: function (pgButton) {
// $("#RptUpload").jqGrid("setGridParam", { postData: { bReload: false } });
//},
loadCompete: function () {
$("#RptUpload").jqGrid("setGridParam", { datatype: 'json', postData: { bReload: false } });
}
});
mygrid.navGrid('#UploadPager', { edit: false, add: false, del: false, search: false, refresh: false });
isGridDefined = true;
}
$("#rptRefresh").click(function (e) {
e.preventDefault();
var Form = $("form[id='FrmDMEUploadDetails']");
Form.validate();
if (Form.valid()) {
RemoveValidatioMessages();
$("#gridContainer").show();
var Year = $("#Year").val();
var Month = $("#Month").val();
if (!isGridDefined)
DefineGrid(Year, Month);
else
$("#RptUpload").jqGrid("setGridParam", { datatype: "json", page: 1, postData: { bReload: true, Year: Year, Month: Month } }).trigger("reloadGrid");
}
else {
$("#RptUpload").clearGridData();
$("#gridContainer").hide();
}
$(".chzn-select-deselect").trigger("liszt:updated");
return false;
});
});
& my action method is as follows
public ActionResult DMEUploadDetailsList(bool bReload, string Year, string Month, string nd, int rows, int page, string sidx, string sord, string filters)
{
DataSet SearchResult = null;
List<ReportData> ResultRows = new List<ReportData>();
JQGridResult Result = new JQGridResult();
if (bReload)
{
SearchResult = DB.ExecuteDataset("ConnectionString", "pc_GetUploadDetail",
new SqlParameter("#Year", Year),
new SqlParameter("#Month", Month));
Common.SetSession(SearchResult, null, "DMEUploadByMonth");
}
else
SearchResult = SessionManager.GetSession().GetAttribute("DMEUploadByMonth") as DataSet;
if (SearchResult != null)
{
DataTable dtSearchResult = SearchResult.Tables[0];
# region Handle server side Filtering, sorting and paging
int totalRecords = dtSearchResult.Rows.Count; //before paging
int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)rows); //--- number of pages
int startIndex = ((page > 0 ? page - 1 : 0) * rows);
if (sidx != "")
{
dtSearchResult.DefaultView.Sort = sidx + " " + sord;
dtSearchResult = dtSearchResult.DefaultView.ToTable();
}
# endregion
for (int i = startIndex; i < dtSearchResult.Rows.Count; i++)
{
ResultRows.Add(new ReportData()
{
ReadingID = Convert.ToInt32(dtSearchResult.Rows[i][0]),
CompanyName = Convert.ToString(dtSearchResult.Rows[i][1]),
PatientID = Convert.ToInt32(dtSearchResult.Rows[i][2]),
PatientName = Convert.ToString(dtSearchResult.Rows[i][3]),
DOB = (dtSearchResult.Rows[i][4] != DBNull.Value ? Convert.ToDateTime(dtSearchResult.Rows[i][4]) : (DateTime?)null),
InsuranceType = Convert.ToString(dtSearchResult.Rows[i][5]),
UploadDate = (dtSearchResult.Rows[i][6] != DBNull.Value ? Convert.ToDateTime(dtSearchResult.Rows[i][6]) : (DateTime?)null)
});
if (ResultRows.Count == rows) break;
}
Result.DataRows = ResultRows;
Result.page = page;
Result.total = totalPages;
Result.records = totalRecords;
}
return Json(Result, JsonRequestBehavior.AllowGet);
}
The problem with current implementation is that my action method DMEUploadDetailsList is not getting called though view model object is getting passed to request successfuly.
& This implementation were working fine when used client side paging & sorting.
Please suggest me If I am missing anything or correct my mistakes to get server side paging & sorting working.
This grid is defined or reloaded on refresh button. Now what I want is to identify whether action method is called on refresh button click or paging & sorting operation?
[ Now I would like to describe the last two sentence of problem statement. It specifies that when my page is loaded grid is not defined. As soon as I select filter & clicks refresh button my grid is defined for first time & reloaded for subsequent clicks of refresh. If you go through the action method code you will see that i am trying to use bReload bit variable for, when it is true [in case of refresh button click] I would like to query data from SQL otherwise from dataset stored in session [in case of paging or sorting request]. Now If you looked at the postData parameter in definition or in reload call I am passing breload as true. Where as I am not aware of how can I override this parameter to false when user request for sorting & paging. Or else if there is any another simple way with which in action method I can get whether this request is of load data or paging & sorting.]
Sorry, but I don't see any implementation of paging in your code. You calculate the number of records which need be skipped and save it in startIndex, but you don't use startIndex later. Your current code just get data from DataTable and returns all items of the table. You need to skip startIndex items. For example you can start for loop from i = startIndex instead of i = 0.
In general it would be more effective to construct SELECT statement in SqlCommand which uses TOP construct or use STORED PROCEDURE like described in the answer (see another answer too). In the way your server code will get from the SQL server only one page of data instead of fetching all records of data and returning only one page.
UPDATED: I would rewrite your client code to something like the following
$(document).ready(function () {
var templateDate = {
width: 80,
fixed: true,
sorttype: "date",
formatter: "date",
formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" }
},
templateInt = { width: 55, fixed: true, sorttype: "integer" },
templateText = {
width: 200,
cellattr: function () {
return 'style="white-space: normal!important;'
}
},
mygrid = $("#RptUpload");
// create the grid without filling it (datatype: "local")
mygrid.jqGrid({
datatype: "local", // to revent initial loading of the grid
postData: {
bReload: true,
Year: function () { return $("#Year").val(); },
Month: function () { return $("#Month").val(); }
},
url: '#Url.Action("DMEUploadDetailsList", "Reports")',
jsonReader: { repeatitems: false, root: "DataRows" },
colNames: [ "#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_OrderID",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_CompanyName",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientID",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientName",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_DOB",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Insurance",
"#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_UploadDate"
],
colModel: [
{ name: "ReadingID", template: templateInt },
{ name: "CompanyName", template: templateText },
{ name: "PatientID", template: templateInt },
{ name: "PatientName", template: templateText },
{ name: "DOB", template: templateDate },
{ name: "InsuranceType", width: 150, template: templateText },
{ name: "UploadDate", template: templateDate }
],
cmTemplate: { align: "center" },
rowNum: 20,
rowList: [20, 50, 100, 200],
pager: "#UploadPager",
caption: "#VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Title",
viewrecords: true,
height: "auto",
width: 770,
hidegrid: false,
headertitles: true,
loadError: function (xhr, status, error) {
alert(status + " " + error);
}
});
mygrid.navGrid("#UploadPager",
{ edit: false, add: false, del: false, search: false, refresh: false });
mygrid.closest(".ui-jqgrid").hide(); // hide the grid
$("#rptRefresh").click(function (e) {
var Form = $("form[id=FrmDMEUploadDetails]");
e.preventDefault();
Form.validate();
if (Form.valid()) {
RemoveValidatioMessages();
mygrid.jqGrid("setGridParam", { datatype: "json" })
.trigger("reloadGrid", [{page: 1}])
.closest(".ui-jqgrid").show(); // show the grid;
} else {
mygrid.clearGridData();
mygrid.closest(".ui-jqgrid").hide(); // hide the grid
}
$(".chzn-select-deselect").trigger("liszt:updated");
return false;
});
});
The grid will be created with datatype: "local", so the url and postData will be ignored. After that it seems to me the usage of bReload property in postData and on the server side seems me unneeded. Nevertheless I included bReload still in the JavaScript code till you remove it from the server code.
Additionally I simplified the colModel by usage of column templates (cmTemplate option of jqGrid and template property of colModel). See the old answer for more information. I removed also some unneeded options of jqGrid which values are default (see "Default" column in the documentation of options).
About usage of new versions of STORED PROCEDURE (pc_GetUploadDetail in your code) you can consider to introduction new version (like pc_GetUploadDetailPaged) which supports more parameters. It will not break existing code which uses the old procedure, but you can still use sorting and paging of data on SQL Server instead of getting all query results to web server and implementing sorting and paging in C#.
I solved my initial problem of jqGrid url not getting called by removing Form.serialize() as postData parameter in jqGrid definition & reload calles. This problem was not related to server side sorting & paging. This was caused due to my previous postData parameter definition as Form.serialize(). Instead I used pass individual parameters to the postData array.
My next problem was related to sorting & paging at server side. In which I want to fetch data from session dataset when user page through the grid or want to sort the grid data; otherwise reload new data by querying SQL server.
According to Oleg answer I must have adopted the simplified way of doing paging & sorting at SQL end instead of in c#. But I was not allowed to add new version of stored procedure as per Oleg suggestion. So I stick to use extra parameter in postData array named operCode like this in grid definition.
postData: {
operCode: "Reload",
Year: function () { return $("#Year").val(); },
InsuranceID: function () { return $("#InsuranceType").val(); },
CustomerID: function () { return $("#CompanyName").val(); }
},
Now I added onPaging & onSortCol event to override operCode postData parameter value like this
onPaging: function (pgButton) {
mygrid.jqGrid("setGridParam", { datatype: 'json', postData: { operCode: "Paging" } });
},
onSortCol: function (index, iCol, sortorder) {
mygrid.jqGrid("setGridParam", { datatype: 'json', postData: { operCode: "Sorting" } });
}
Now whenever user clicks refresh button operCode is sent as Reload, on paging as "Paging" & on sorting as "Sorting"
My server side action method code is as follows
public ActionResult DMEUploadDetails(string operCode, string Year, string Month, string nd, int rows, int page, string sidx, string sord, string filters)
{
DataSet SearchResult = null;
List<ReportData> ResultRows = new List<ReportData>();
JQGridResult Result = new JQGridResult();
if (operCode == "Reload")
{
SearchResult = DB.ExecuteDataset("ConnectionString", "pc_GetUploadDetail",
new SqlParameter("#Year", Year),
new SqlParameter("#Month", Month));
Common.SetSession(SearchResult, null, "POXMonthlyUploads");
}
else
SearchResult = (SessionManager.GetSession().GetAttribute("POXMonthlyUploads") as System.Web.UI.WebControls.GridView).DataSource as DataSet;
if (SearchResult != null)
{
DataTable dtSearchResult = SearchResult.Tables[0];
# region Handle server side Filtering, sorting and paging
int totalRecords = dtSearchResult.Rows.Count; //before paging
int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)rows); //--- number of pages
int startIndex = ((page > 0 ? page - 1 : 0) * rows);
if (sidx != "" && operCode == "Sorting")
{
dtSearchResult.DefaultView.Sort = sidx + " " + sord;
dtSearchResult = dtSearchResult.DefaultView.ToTable();
SearchResult.Tables.RemoveAt(0);
SearchResult.Tables.Add(dtSearchResult);
Common.SetSession(SearchResult, null, "POXMonthlyUploads");
}
# endregion
for (int i = startIndex; i < dtSearchResult.Rows.Count; i++)
{
ResultRows.Add(new ReportData()
{
//code to fill data to structure object
});
if (ResultRows.Count == rows) break;
}
Result.DataRows = ResultRows;
Result.page = page;
Result.total = totalPages;
Result.records = totalRecords;
}
return Json(Result, JsonRequestBehavior.AllowGet);
}
Very much Thanks to Oleg for giving me some extra knowledge about jqGrid & giving me good idea about server side paging & sorting.

how to set variable value from the server response extjs 4

forum member I am having one problem in setting the value of my view from the server response I am receiving
I am using the MVC architechture of the extjs 4. My store is loaded perfectly and my taskstore is defined as below
Ext.define('gantt.store.taskStore', {
extend: 'Gnt.data.TaskStore',
model: 'gantt.model.ResourceTask',
storeId: 'taskStore',
autoLoad : true,
autoSync : true,
proxy : {
type : 'ajax',
api: {
read: 'task/GetTask.action',
create: 'task/CreateTask.action',
destroy: 'task/DeleteTask.action',
update: 'task/UpdateTask.action'
},
writer : new Ext.data.JsonWriter({
//type : 'json',
root : 'taskdata',
encode : true,
writeAllFields : true
}),
reader : new Ext.data.JsonReader({
totalPropery: 'total',
successProperty : 'success',
idProperty : 'id',
type : 'json',
root: function (o) {
if (o.taskdata) {
return o.taskdata;
} else {
return o.children;
}
}
})
}
});
but what I want to do is that as soon as the store loaded I want to assign the server response data to one of the variable in my javascript.
I tried to add the value from the beforeload function of view, but not able to do so.
my view code is given as below
var result = Ext.JSON.decode('{"calendardata": [{"startdate": 1330281000000,"enddate": 1330284600000,"id": 3,"title": "mon"}],"total": 1,"success": true}');
//var start = new Date(2012, 2, 26),
//end = Sch.util.Date.add(start, Sch.util.Date.MONTH, 30);
var start_d = new Date(result.calendardata[0].startdate);
var end_d = new Date(result.calendardata[0].enddate);
var start = new Date(start_d.getFullYear(), start_d.getMonth(), start_d.getDate());
end = Sch.util.Date.add(start, Sch.util.Date.MONTH, 30);
console.log("YEAR ::"+start.getFullYear()+"MONTH ::"+start.getMonth()+"DAY ::"+start.getDate());
console.log("YEAR ::"+end.getFullYear()+"MONTH ::"+end.getMonth()+"DAY ::"+end.getDate());
//create the downloadframe at the init of your app
this.downloadFrame = Ext.getBody().createChild({
tag: 'iframe'
, cls: 'x-hidden'
, id: 'iframe'
, name: 'iframe'
});
//create the downloadform at the init of your app
this.downloadForm = Ext.getBody().createChild({
tag: 'form'
, cls: 'x-hidden'
, id: 'form'
, target: 'iframe'
});
var printableMilestoneTpl = new Gnt.template.Milestone({
prefix : 'foo',
printable : true,
imgSrc : 'resources/images/milestone.png'
});
var params = new Object();
Ext.define('gantt.view.projectmgt.projectGanttpanel', {
extend: "Gnt.panel.Gantt",
id: 'projectganttpanel',
alias: 'widget.projectganttpanel',
requires: [
'Gnt.plugin.TaskContextMenu',
'Gnt.column.StartDate',
'Gnt.column.EndDate',
'Gnt.column.Duration',
'Gnt.column.PercentDone',
'Gnt.column.ResourceAssignment',
'Sch.plugin.TreeCellEditing',
'Sch.plugin.Pan',
'gantt.store.taskStore',
'gantt.store.dependencyStore'
],
leftLabelField: 'Name',
loadMask: true,
//width: '100%',
// height: '98%',
startDate: start,
endDate: end,
multiSelect: true,
cascadeChanges: true,
viewPreset: 'weekAndDayLetter',
recalculateParents: false,
showTodayLine : true,
showBaseline : true,
initComponent: function() {
var me = this;
me.on({
scope: me,
beforeload: function(store,records,options) {
console.log('BEFORE LOAD YAAR panel'+records.params);
if(records.params['id'] != null)
{
return true;
}
else
{
return false;
}
}
});
TaskPriority = {
Low : 0,
Normal : 1,
High : 2
};
var taskStore = Ext.create('gantt.store.taskStore');
var dependencyStore = Ext.create('gantt.store.dependencyStore');
Ext.apply(me, {
taskStore: taskStore,
dependencyStore: dependencyStore,
// Add some extra functionality
plugins : [
Ext.create("Gnt.plugin.TaskContextMenu"),
Ext.create('Sch.plugin.TreeCellEditing', {
clicksToEdit: 1
}),
Ext.create('Gnt.plugin.Printable', {
printRenderer : function(task, tplData) {
if (task.isMilestone()) {
return;
} else if (task.isLeaf()) {
var availableWidth = tplData.width - 4,
progressWidth = Math.floor(availableWidth*task.get('PercentDone')/100);
return {
// Style borders to act as background/progressbar
progressBarStyle : Ext.String.format('width:{2}px;border-left:{0}px solid #7971E2;border-right:{1}px solid #E5ECF5;', progressWidth, availableWidth - progressWidth, availableWidth)
};
} else {
var availableWidth = tplData.width - 2,
progressWidth = Math.floor(availableWidth*task.get('PercentDone')/100);
return {
// Style borders to act as background/progressbar
progressBarStyle : Ext.String.format('width:{2}px;border-left:{0}px solid #FFF3A5;border-right:{1}px solid #FFBC00;', progressWidth, availableWidth - progressWidth, availableWidth)
};
}
},
beforePrint : function(sched) {
var v = sched.getSchedulingView();
this.oldRenderer = v.eventRenderer;
this.oldMilestoneTemplate = v.milestoneTemplate;
v.milestoneTemplate = printableMilestoneTpl;
v.eventRenderer = this.printRenderer;
},
afterPrint : function(sched) {
var v = sched.getSchedulingView();
v.eventRenderer = this.oldRenderer;
v.milestoneTemplate = this.oldMilestoneTemplate;
}
})
],
eventRenderer: function (task) {
var prioCls;
switch (task.get('Priority')) {
case TaskPriority.Low:
prioCls = 'sch-gantt-prio-low';
break;
case TaskPriority.Normal:
prioCls = 'sch-gantt-prio-normal';
break;
case TaskPriority.High:
prioCls = 'sch-gantt-prio-high';
break;
}
return {
cls: prioCls
};
},
// Setup your static columns
columns: [
{
xtype : 'treecolumn',
header: 'Tasks',
dataIndex: 'Name',
width: 150,
field: new Ext.form.TextField()
},
new Gnt.column.StartDate(),
new Gnt.column.Duration(),
new Gnt.column.PercentDone(),
{
header: 'Priority',
width: 50,
dataIndex: 'Priority',
renderer: function (v, m, r) {
switch (v) {
case TaskPriority.Low:
return 'Low';
case TaskPriority.Normal:
return 'Normal';
case TaskPriority.High:
return 'High';
}
}
},
{
xtype : 'booleancolumn',
width : 50,
header : 'Manual',
dataIndex : 'ManuallyScheduled',
field : {
xtype : 'combo',
store : [ 'true', 'false' ]
}
}
],
tooltipTpl: new Ext.XTemplate(
'<h4 class="tipHeader">{Name}</h4>',
'<table class="taskTip">',
'<tr><td>Start:</td> <td align="right">{[Ext.Date.format(values.StartDate, "y-m-d")]}</td></tr>',
'<tr><td>End:</td> <td align="right">{[Ext.Date.format(Ext.Date.add(values.EndDate, Ext.Date.MILLI, -1), "y-m-d")]}</td></tr>',
'<tr><td>Progress:</td><td align="right">{PercentDone}%</td></tr>',
'</table>'
).compile()
});
me.callParent(arguments);
}
});
the reason I am not able to set the value of variable I used to set it using static data. To set the static data I am using the below code
var result = Ext.JSON.decode('{"calendardata": [{"startdate": 1330281000000,"enddate": 1330284600000,"id": 3,"title": "mon"}],"total": 1,"success": true}');
var start_d = new Date(result.calendardata[0].startdate);
var end_d = new Date(result.calendardata[0].enddate);
var start = new Date(start_d.getFullYear(), start_d.getMonth(), start_d.getDate());
end = Sch.util.Date.add(start, Sch.util.Date.MONTH, 30);
but instead of this static data I want to set the start and end value as soon as the store loads and server response is received.
please suggest me some solution I can apply here.
I am receiving the jsondata as
{
"taskdata": [{
"startdate": 1330281000000,
"enddate": 1330284600000,
"id": 3,
"title": "mon"
}],
"total": 1,
"success": true
}
I am using extjs 4 with MVC architecture and JAVA as my server side technology.
First of all your question is kind of badly formulated. You have too much code and not really clear what are you trying to ask. In a future try to isolate a particular problem you're dealing with if you want to get quick and proper answer.
Second, load operation is asynchronous. You just specified store as 'autoLoad', but I don't see anywhere where you subscribe to its load event. Most likely your problem is trying to get something of the store while it's not yet loaded. Try to set autoLoad: false, load store manually and subscribe to its 'load' event to populate your view.