i have a telerik mvc grid where the excel export function fails because the read action of the grid has extra parameters.
the read action looks like this :
public ActionResult My_ReadAction([DataSourceRequest]DataSourceRequest request, string startDate, string endDate)
{
DateTime _startDate, _endDate;
_startDate = DateTime.ParseExact(startDate, "yyyyMMdd", CultureInfo.InvariantCulture);
_endDate = DateTime.ParseExact(endDate, "yyyyMMdd", CultureInfo.InvariantCulture);
IQueryable<CM_DISTRIBUTION_SCHEDULE> cm_distribution_schedule = db.CM_DISTRIBUTION_SCHEDULE
.Where(x => x.REF_DATE >= _startDate && x.REF_DATE <= _endDate);
DataSourceResult result = cm_distribution_schedule.ToDataSourceResult(request, cM_DISTRIBUTION_SCHEDULE => new
{
RECORD_ID = cM_DISTRIBUTION_SCHEDULE.RECORD_ID,
REF_DATE = cM_DISTRIBUTION_SCHEDULE.REF_DATE,
BRANCH_ID = cM_DISTRIBUTION_SCHEDULE.BRANCH_ID,
CURRENCY = cM_DISTRIBUTION_SCHEDULE.CURRENCY,
FORECAST_AMOUNT = cM_DISTRIBUTION_SCHEDULE.FORECAST_AMOUNT
});
return Json(result);
}
and the grid :
#(Html.Kendo().Grid<MyClass.MyViewModel>().Name("BranchFcast").AutoBind(false) .HtmlAttributes(new { style = "height: 100%; border: 0;" })
.Columns(columns =>
{
columns.Bound(c => c.REF_DATE).Title("Forecast Date").Format("{0:d}").Width(130);
columns.ForeignKey(f => f.BRANCH_ID, (System.Collections.IEnumerable)ViewData["branches"], "BranchId", "BranchName").Title("Branch").Width(200);
columns.ForeignKey(f => f.CURRENCY, (System.Collections.IEnumerable)ViewData["currencies"], "CurrencyId", "CurrencyName").Title("Currency").Width(150);
columns.Bound(c => c.FORECAST_AMOUNT).Title("Forecast Amount").Format("{0:c}").Width(150);
columns.Bound(c => c.TXN_AMOUNT).Title("Amended Forecast").Width(150);
})
.ToolBar(toolbar => {
toolbar.Excel();
}).Excel(excel => excel.FileName("DistSchedule.xlsx").Filterable(true).ProxyURL(Url.Action("Excel_Export_Save", "DistSched")).AllPages(true))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Model(model =>
{
model.Id(p => p.RECORD_ID);
model.Field(p => p.RECORD_ID).Editable(false);
model.Field(p=> p.REF_DATE).DefaultValue(DateTime.Today);
}
)
.Sort(s => s.Add(f => f.REF_DATE).Descending()).Read(read => read.Action("My_ReadAction", "Controller")))
)
So when the export button is clicked, it fires My_ReadAction but doesnt pass the parameter, causing the controller action to fail.
Is there a way to modify the export events such that i can pass the parameters. Any other workaround is welcome.
Add a .Data() fluent method to the Ajax DataSource settngs and implement a JavaScript function that will return a plain object with the two dates. This is the recommended way to pass custom parameters to the Grid's Read action method.
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/binding/ajax-binding#pass-additional-data-to-action-methods
Related
I am trying to open kendo grid in popup on clicking of link. Kendo grid Opens in popup perfectly, but filtering and sorting functionality is not working. I am using server side Operation. When I sort particular column In controller side in DatasourceRequest I always gets value as null.
Any help is highly appreciated..
<div class="panel-body" id="countryImageData">
#(Html.Kendo().Grid(Model.GlobalInventoryImages)
.Name("InventoryCountryImageDetailsGrid")
.Columns(columns =>
{
columns.Bound(p => p.SmartInventoryID).Hidden().Title("SPC #").HtmlAttributes(new { #id = "CountrySmartInventory_Grid" });
columns.Bound(p => p.SubwayProductCode).Width(50).Title("SPC #").HtmlAttributes(new { #id = "CountrySubwayProductCode_Grid" });
columns.Bound(p => p.GlobalCaseImageName).Width(100).Title("Case Images").HtmlAttributes(new { #id = "GlobalCaseGraphicName_Grid" }).ClientTemplate(" #=GlobalCaseImageName# ");
columns.Bound(p => p.GlobalInnerImageName).Width(100).Title("Inner Images ").HtmlAttributes(new { #id = "GlobalInnerImageName_Grid" }).ClientTemplate(" #=GlobalInnerImageName# ");
columns.Bound(p => p.CountryNames).Width(100).Title("Country").HtmlAttributes(new { #id = "CountryNames_Grid" });
})
.Pageable(pager => pager.PageSizes(new int[] { 25, 50, 75, 100 }).Input(true))
.Sortable(e => e.AllowUnsort(true).SortMode(GridSortMode.MultipleColumn))
.Scrollable()
.ColumnMenu()
.NoRecords("No Records")
.Selectable(e => e.Mode(GridSelectionMode.Multiple))
.Filterable()
.ColumnResizeHandleWidth(10)
.ColumnResizeHandleWidth(10)
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.HtmlAttributes(new { #class = "custom-kendo-grid custom-kendo-grid-inv" })
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.PageSize(25)
.Read(read => read.Action("InventoryImage_Read", "Inventory").Data("function onCountryAdditonalData(){ return {subwayProductCode: $('#SubwayProductCode').val()};}"))
)
)
</div>
With MVC you have to add the following in your dataSource:
type: 'aspnetmvc-ajax'
for the filter and sort not to be null. Also, your Action method in your MVC Controller must have parameters set up like so:
public async Task<ActionResult> InventoryImage_Read([DataSourceRequest] DataSourceRequest )
You didn't post your MVC Controller Action so I wasn't sure if you had that part set up correctly. I hope this helps.
App type: ASP.NET MVC with Kendo framework
Problem Encountered: The detail template is not firing the controller action method. Please find the attached screenshot also. I checked it under the firebug window also, there is no ajax call to the controller action method "PublishedImportFiles_Read". This is making me crazy and annoying. No error is thrown or shown for this anomaly. I guess i am missing something very small.
Please help.
MVC - View Code
<div class="gapLeft gapBelow20" style="width:70%;">
#(Html.Kendo().Grid<ViewModels.PublishedImportViewModel>()
.Name("GridImport")
.Columns(columns =>
{
columns.Bound(p => p.TemplateGroup).Title("Template Group").Width("120px");
columns.Bound(p => p.TaxYear).Title("Tax Year").Width("70px");
columns.Bound(p => p.FileDescription).Title("Description").Width("200px");
columns.Bound(p => p.DatePublished).Title("Published Date").Format("{0:MM/dd/yyyy}").Width("100px");
columns.Bound(p => p.PublishedBy).Title("Published By").Width("100px");
})
.Scrollable()
.ClientDetailTemplateId("tplGridImport")
.Events(et => et.DataBound(fnCall.Replace("functionName", "gridImpDataBound")))
.Events(et => et.DetailInit(fnCall.Replace("functionName", "gridImpChildInit")))
.HtmlAttributes(new { style = "height:300px;" })
.DataSource(ds => ds.Ajax().ServerOperation(false)
.Read(read => { read.Action("PublishedImport_Read", "Import"); })
.Model(m => { m.Id(p => p.TemplateGroupID); })
)
)
</div>
<script id="tplGridImport" type="text/kendo-tmpl">
#(Html.Kendo().Grid<ViewModels.PublishedImportViewModel>()
.Name("GridImport_#=TemplateGroupID#")
.Columns(columns =>
{
columns.Bound(c => c.TemplateGroup).Title("Template Group").Width("120px");
columns.Bound(c => c.TaxYear).Title("Tax Year").Width("70px");
})
.DataSource(dsx => dsx.Ajax()
.Read(rd => { rd.Action("PublishedImportFiles_Read", "Import"); })
)
.ToClientTemplate()
)
</script>
Import Controller ActionResult Method:
[OutputCache(Duration = 0)]
public ActionResult PublishedImportFiles_Read([DataSourceRequest] DataSourceRequest request)
{
int groupID = 5;
IEnumerable<PublishedImportViewModel> pubVM = Enumerable.Empty<PublishedImportViewModel>();
var pubRecords = base.ScenarioMangtService.GetPublishedImportFilesByTemplateGroup(ClientID, SelectedYear, groupID);
pubVM = pubRecords.Select(s => new PublishedImportViewModel
{
ImportFileJobID = s.ImportFileJobID,
TemplateGroupID = s.TemplateGroupID,
TemplateGroup = s.TemplateGroup,
FileName = s.FileName,
FileDescription = s.FileDescription,
TaxYear = SelectedYear,
DatePublished = s.DatePublished,
PublishedBy = s.PublishedBy
});
return Json(pubVM.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
There was nothing wrong with the KendoGrid code. Strangely, there was a javascript error in another js file. And for some weird reason, it was breaking the binding of the detail template grid.
So when i commented the other broken code in another file, this grid starts working automatically.
I'm using Kendo MVC grid to display data. I have to filter the data based on the url clicked by the user. Below is the code for Kendo grid
View
#(Html.Kendo().Grid<WebApplication2.ApplicationViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.ApplicationStatus).Width(150);
columns.Bound(c => c.StartDate).Width(150).Filterable(ftb => ftb.Cell(cell => cell.Operator("equals")));
columns.Bound(c => c.EndDate).Width(150).Filterable(ftb => ftb.Cell(cell => cell.Operator("equals"))).Groupable(false);
})
.HtmlAttributes(new { style = "height: 500px;width:100%" })
.Groupable()
.Scrollable()
.Filterable(ftb => ftb.Mode(Kendo.Mvc.UI.GridFilterMode.Row)) // Filter Code
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.Read(read => read.Action("FetchData", "Home"))
.Filter(f => f.Add(p => p.ApplicationStatus).IsEqualTo(ViewBag.ApplicationStatus))
.Filter(f => f.Add(p => p.StartDate).IsGreaterThanOrEqualTo(Convert.ToDateTime(ViewBag.FromDate)))
.Filter(f => f.Add(p => p.StartDate).IsLessThanOrEqualTo(Convert.ToDateTime(ViewBag.ToDate)))
.PageSize(KendoGridConstants.KendoGridDefaultPageSize)
)
)
Controller Code:
public ActionResult ApplicationGrid(string ApplicationStatus, string fromDate, string toDate)
{
ViewBag.ApplicationStatus = ApplicationStatus == null ? "All" : ApplicationStatus;
ViewBag.FromDate = fromDate == null ? DateTime.Now.ToShortDateString() : Convert.ToDateTime(fromDate).ToShortDateString();
ViewBag.ToDate = toDate == null ? DateTime.Now.ToShortDateString() : Convert.ToDateTime(toDate).ToShortDateString();
return View();
}
public ActionResult FetchData([DataSourceRequest]DataSourceRequest request)
{
var applicationList = Dbcontext.ApplicationStatus;
return Json(applicationList.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
If I keep only one filter on StartDate it works fine but if I keep both the filters, it is showing me some irrelevant data. I need to filter on date range. Any other alternative is also fine.
I know this is really old, but I had the same problem, couldn't find documentation, and ended up, as always, on Stack Overflow. So I'm contributing my solution.
Need to add additional and / or operators to the Filter statement on the DataSource:
.Read(read => read.Action("FetchData", "Home"))
.Filter(f => f.Add(p => p.StartDate).IsGreaterThanOrEqualTo(Convert.ToDateTime(ViewBag.FromDate)))
.And().IsLessThanOrEqualTo(Convert.ToDateTime(ViewBag.ToDate)))
I am using Kendo Grid for MVC.
Following is my controller and actions.
public class ComplainController : Controller
{
private MSMContext db = new MSMContext();
public ActionResult Index([DataSourceRequest]DataSourceRequest request)
{
var cOMPLAINs = db.COMPLAINs.Include(c => c.MASTER_FAULT);
var model = cOMPLAINs.Select(o => new
{
JOBSHEET_NO = o.JOBSHEET_NO,
CUSTOMER_NAME = o.CUSTOMER_NAME,
CUSTOMER_MOBILE = o.CUSTOMER_MOBILE,
COMPANY_NAME = o.COMPANY_NAME,
MODEL_NAME = o.MODEL_NAME
});
return Json(model.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
public ActionResult GetData([DataSourceRequest]DataSourceRequest request)
{
var model = db.COMPLAINs.Select(o => new
{
JOBSHEET_NO = o.JOBSHEET_NO,
CUSTOMER_NAME = o.CUSTOMER_NAME,
CUSTOMER_MOBILE = o.CUSTOMER_MOBILE,
COMPANY_NAME = o.COMPANY_NAME,
MODEL_NAME = o.MODEL_NAME
});
return Json(model.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
}
Now Following is my Kendo Grid Code I am using in a view.
#(Html.Kendo().Grid<WebMSM.Models.COMPLAIN>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.JOBSHEET_NO).Width(150);
columns.Bound(p => p.CUSTOMER_NAME).Width(400);
columns.Bound(p => p.CUSTOMER_MOBILE).Width(200);
columns.Bound(p => p.COMPANY_NAME).Width(200);
columns.Bound(p => p.MODEL_NAME).Width(150);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GetData", "Complain"))
)
)
If I use GetData action, Kendo Grid is working fine with all data shown.
But if I use Index action, Kendo Grid displays but without data.
While using Index action, following json data is displayed without any page layout and HTML.
{"Data":[{"JOBSHEET_NO":1018,"CUSTOMER_NAME":"HEMAL RATHOD","CUSTOMER_MOBILE":"9825369987","COMPANY_NAME":"SAMSUNG","MODEL_NAME":"NOTE 3"},{"JOBSHEET_NO":1019,"CUSTOMER_NAME":"MUKESH CHAUHAN","CUSTOMER_MOBILE":"9825305305","COMPANY_NAME":"APPLE","MODEL_NAME":"IPHONE 6"}],"Total":2,"AggregateResults":null,"Errors":null}
What am I missing?
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GetData", "Complain"))
)
)
needs to be changed to
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Index", "Complain"))
)
)
if you want to get it working with "Index". If your datasource never calls "Index" action method, then your grid will always be empty.
From the samples and documentation, it looks like if I want to update one row (or do a batch update) in a Telerik grid, I also need to refresh the data in the entire grid.
Is there a way to just update that one row on the client and not return all the grid data every time I want to do an update? It seems extremely wasteful to keep returning that much data every time.
Even if I do a batch update, why do I need to return all the new data?
Generally a database has many users, and your user interface may be accessed by multiple people. If the grid is going to update, then it will include any other changes that may have happened to the data since the grid originally loaded.
The grid allows you to limit the number of records that are shown at a time via the paging option. On our project we are loading the grid with AJAX, and using IQueryable's in the controller. When we call ToDataSourceResult(request) on the IQueryable, it only retrieves the data that is needed, and does not load the full table from the database.
On the Razor View:
#(Html.Kendo().Grid<WebApp.ViewModels.AccountViewModel>()
.Name("Accounts")
.Columns(columns =>
{
columns.Bound(c => c.AccountNumber);
columns.Bound(c => c.Name);
columns.Bound(c => c.Address1);
columns.Bound(c => c.Address2);
columns.Bound(c => c.City);
columns.Bound(c => c.State);
columns.Bound(c => c.Zip);
columns.Bound(c => c.PrimaryContact).Title("Contact");
})
.Filterable(filterable => filterable
.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear()
.Contains("Contains")
.DoesNotContain("Doesn't Contain")
)
)
)
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new int[] { 5, 10, 20, 50, 100, 500 })
.ButtonCount(5)
)
.DataSource(dataSource => dataSource
.Ajax()
.Sort(sort => sort.Add("Name").Ascending())
.PageSize(20)
.Read(read => read.Action("Account_Read", "Account"))
)
)
Then in the controller:
public ActionResult Account_Read([DataSourceRequest] DataSourceRequest request)
{
var jsonlist = GetAccounts()
.Select(sa => new AccountViewModel
{
ID = sa.ID,
AccountNumber = sa.AccountNumber,
Name = sa.Name,
Address1 = sa.Address1,
Address2 = sa.Address2,
City = sa.City,
State = sa.State,
Zip = sa.Zip,
PrimaryContact = sa.User.FirstName + " " + sa.User.LastName
}
).ToDataSourceResult(request);
return Json(jsonlist);
}
UPDATE
We have an inline edit form on one of our Kendo grids. It took us a bit to get it how we watned. In the Razor View:
#(Html.Kendo().Grid<DataViewModel>()
.Name("Data")
.Columns(columns =>
{
columns.Bound(c => c.FieldName)
.EditorTemplateName("DataFieldName")
.Title("Item Name")
.Width(200);
columns.Bound(c => c.TextValue)
.Title("Text");
columns.Command(command => { command.Edit(); command.Destroy(); })
.Title("Actions")
.Width(172);
})
.Filterable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new int[] { 5, 10, 20, 50, 100 })
.ButtonCount(5)
)
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.Ajax()
.Sort(sort => sort.Add("CreatedDate").Descending())
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(pd => pd.ID);
model.Field(pd => pd.CreatedDate).Editable(false);
model.Field(pd => pd.ValuesID).DefaultValue(Model.Values.ID);
})
.Read(read => read.Action("Data_Read", "History", new { ValuesID = Model.Values.ID }))
.Create(update => update.Action("Data_Create", "History"))
.Update(update => update.Action("Data_Update", "History"))
.Destroy(update => update.Action("Data_Destroy", "History"))
)
)
<script type="text/javascript">
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
</script>
In order to use the Kendo date time picker for the date option, we had to create a custom editor template. We created a new folder under Views >> Shared >> EditorTemplates. The file name is DataFieldName.cshtml:
#model WebApp.ViewModels.DataViewModel
#using WebApp.ViewModels
#(Html.Kendo().ComboBox()
.Name("FieldName")
.Placeholder("Select/Create Item Name")
.DataTextField("Name")
.DataValueField("Name")
.Filter(FilterType.Contains)
.DataSource(source => source
.Read(read => read.Action("GetFieldNames", "History"))
)
)
Then the controller has all of the action results for the AJAX calls:
[HttpPost]
public ActionResult Data_Create(DataViewModel DataIn)
{
var Data = new Data();
Data.ValuesID = DataIn.ValuesID;
Data.FieldName = DataIn.FieldName;
Data.TextValue = DataIn.TextValue;
if (DataIn.TimeValue != null) Data.TimeValue = DataIn.TimeValue;
if (ModelState.IsValid)
{
db.Datas.Add(Data);
db.SaveChanges();
}
return RedirectToAction("EditValue", new
{
ValueID = DataIn.ValuesID,
tankID = db.Values.FirstOrDefault(pv => pv.ID == DataIn.ValuesID).TankID
});
}
[HttpPost]
public ActionResult Data_Update(DataViewModel DataIn)
{
var Data = db.Datas.Find(DataIn.ID);
Data.FieldName = DataIn.FieldName;
Data.TextValue = DataIn.TextValue;
if (DataIn.TimeValue != null) Data.TimeValue = DataIn.TimeValue;
if (ModelState.IsValid)
{
db.Entry(Data).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("EditValue", new
{
ValueID = DataIn.ValuesID,
tkID = db.Values.FirstOrDefault(pv => pv.ID == DataIn.ValuesID).tkID
});
}
[HttpPost]
public ActionResult Data_Destroy(DataViewModel DataIn)
{
var Data = db.Datas.Find(DataIn.ID);
db.Datas.Remove(Data);
db.SaveChanges();
return RedirectToAction("EditValue", new
{
ValueID = DataIn.ValuesID,
tkID = db.Values.FirstOrDefault(pv => pv.ID == DataIn.ValuesID).tkID
});
}
public ActionResult GetFieldNames()
{
var jsonList = db.Datas
.Select(pd => new
{
Name = pd.FieldName
})
.Distinct()
.OrderBy(pd => pd.Name)
.ToList();
return Json(jsonList, JsonRequestBehavior.AllowGet);
}