Populating ASP.NET MVC Kendo Grid Via Ajax Call - kendo-grid

I have an MVC Kendo Grid and I want to fill it via a jQuery Ajax Call. I used jQuery 'each' method to do it like this :
function FillRowsByRequest(reqRow) {
var readDataUrl = '#Url.Action("GetGoodsByReq")';
var targetGrid = $("#storeReceiptRowsGrid").data("kendoGrid");
$.get(readDataUrl, { reqseq: reqRow }, function (d, t, j) {
var counter = 0;
targetGrid.cancelChanges();
$(d).each(function (i, e) {
targetGrid.dataSource.insert(counter++, {
GOOD_ID: e.GOOD_ID,
GOOD_CODE: e.GOOD_CODE,
GOOD_CODE_DESC: e.GOOD_CODE_DESC,
GOOD_DESC: e.GOOD_DESC
});
});
});
}
I can see my Kendo Grid that is filled with data ( not completely ) but the thing is that when I click on the Save button, it does not trigger the Save Action Method and consequently nothing is inserted in the table and Grid contains nothing after it is refreshed.
#(Html.Kendo()
.Grid<Tpph.Models.STORE_RECEIPT_ROW>()
.Name("storeReceiptRowsGrid")
.Columns(columns =>
{
columns.Bound(o => o.GOOD_ID).Title("Good ID").HtmlAttributes(new { #class = "goodid" }).Visible(false);
columns.Bound(o => o.GOOD_CODE).Title("Good Code").HtmlAttributes(new { #class = "goodcode" }).Width(100);
columns.Bound(o => o.GOOD_CODE_DESC).Title("Good Code Desc").HtmlAttributes(new { #class = "goodcodedesc" }).Width(100);
columns.Bound(o => o.GOOD_DESC).Title("Good Desc").HtmlAttributes(new { #class = "gooddesc" }).Width(155);
})
.ToolBar(toolbar =>
{
toolbar.Create().Text("New Row").HtmlAttributes(new { #class = "k-primary", style = "background-color: #e6ffe6; border-color: #10c4b2; min-width: 100px; color: black;" });
toolbar.Save().Text("Save").SaveText("Save").CancelText("Cancel").HtmlAttributes(new { #class = "k-primary", style = "background-color: #e6ffe6; border-color: #10c4b2; min-width: 100px; color: black;" });
})
.ColumnMenu()
.Selectable(s => s.Type(GridSelectionType.Row))
.Sortable()
.Editable(editable => editable.Mode(GridEditMode.InCell).DisplayDeleteConfirmation("Delete?"))
.Filterable()
.Groupable()
.Scrollable()
.Pageable(p => p.Refresh(true))
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.Events(ev => ev.RequestEnd("storeReceiptRowsGridOnRequestEnd"))
.Batch(true)
.ServerOperation(true)
.Model(model =>
{
model.Id(p => p.GOOD_ID);
})
.Read(read => read.Action("StoreReceiptRowsRead", "StorageForms"))
.Update(u => u.Action("StoreReceiptRowsEdit", "StorageForms"))
.Create(c => c.Action("StoreReceiptRowsCreate", "StorageForms"))
.Destroy(de => de.Action("StoreReceiptRowsDestory", "StorageForms")))
.Events(ev =>
{
ev.DataBound("storeReceiptRowsGridOnBound");
})
)
How can I do this ?

After lots of struggling with this issue, I finally found out that the Kendo Grid triggers the CRUD Action Methods only when the "dirty" attribute of a row is set to true. ( dirty flag is a tiny little red triangle which appears in the corner of a cell when you edit that cell ). So the solution to this issue is setting dirty flag of each row to true like this :
.set("dirty", true);
So my final JavaScript Code is like this :
function FillRowsByRequest(reqRow) {
var readDataUrl = '#Url.Action("GetGoodsByReq")';
var targetGrid = $("#storeReceiptRowsGrid").data("kendoGrid");
$.get(readDataUrl, { reqseq: reqRow }, function (d, t, j) {
var counter = 0;
targetGrid.cancelChanges();
$(d).each(function (i, e) {
targetGrid.dataSource.insert(counter++, {
GOOD_ID: e.GOOD_ID,
GOOD_CODE: e.GOOD_CODE,
GOOD_CODE_DESC: e.GOOD_CODE_DESC,
GOOD_DESC: e.GOOD_DESC
}).set("dirty", true);
});
});
}

Related

DEVEXTREME Save all selected data in grid inside edit form to database

multiple select item in Edit form with grid
How to save the data included the selected item at grid using DEVEXTREME.
The condition now is i can show the grid but now i struggle on get all the data inside the grid to save it and bring it to database, including need to show it again when the user want to edit the data
Template:
#using (Html.DevExtreme().NamedTemplate("EmbeddedDataGridMultiple"))
{
#(Html.DevExtreme().DataGrid()
.ID("PrincipalGrid")
.DataSource(d => d.WebApi().Controller("MasterPrincipal").LoadAction("GetPrincipalData").Key("PrincipalId"))
.Columns(columns => {
columns.Add().DataField("Principal");
columns.Add().DataField("Description");
})
.HoverStateEnabled(true)
.Paging(p => p.PageSize(10))
.FilterRow(f => f.Visible(true))
.Scrolling(s => s.Mode(GridScrollingMode.Virtual))
.Height(345)
.Selection(s => s.Mode(SelectionMode.Multiple))
.SelectedRowKeys(new JS(#"component.option(""value"")"))
.OnSelectionChanged(#<text>
function(selectedItems) {
var keys = selectedItems.selectedRowKeys;
component.option("value", keys);
}
</text>)
)
}
Form
#(Html.DevExtreme().DataGrid<MasterGroupQuotaValidateModel>
()
.ID("gridData")
.ShowBorders(true)
.DataSource(d => d.Mvc().Controller("MasterGroupQuota")
.LoadAction("GetGroupQuota")
.Key("IdGroup")
.UpdateAction("UpdateMasterGroupQuota")
.DeleteAction("DeleteMasterGroupQuota")
.InsertAction("InsertMasterGroupQuota")
)
.RemoteOperations(true)
.Columns(columns =>
{
columns.AddFor(m => m.RowNumber).Caption("No").Width(70);
columns.AddFor(m => m.GroupQuotaId).Visible(false);
columns.AddFor(m => m.SitePlan)
.Lookup(lookup => lookup
.DataSource(d => d.WebApi().Controller("MasterSite").LoadAction("GetSitePlan").Key("SiteId"))
.DisplayExpr("SitePlan")
.ValueExpr("SiteId")
).ValidationRules(rules =>
{
rules.AddAsync().ValidationCallback("CheckGroupQuota").Message("This Site is already registered with the follwoing GroupQuota and Principal");
}); ;
columns.AddFor(m => m.Description).Caption("Group Quota").ValidationRules(rules =>
{
rules.AddAsync().ValidationCallback("CheckGroupQuota").Message("This Group Quota is already registered with the follwoing Site Plan and Principal");
});
columns.AddFor(m => m.Principal)
.Lookup(lookup => lookup
.DataSource(d => d.WebApi().Controller("MasterPrincipal").LoadAction("GetPrincipalData").Key("PrincipalId"))
.DisplayExpr("Principal")
.ValueExpr("PrincipalId")
).ValidationRules(rules =>
{
rules.AddAsync().ValidationCallback("CheckGroupQuota").Message("This Principal is already registered with the follwoing GroupQuota and Site Plan");
});
})
.Paging(paging => paging.PageSize(5))
.Pager(pager =>
{
pager.Visible(true);
pager.ShowPageSizeSelector(true);
pager.AllowedPageSizes(new JS("[5, 10, 'all']"));
pager.ShowInfo(true);
pager.ShowNavigationButtons(true);
})
.Sorting(sorting=> sorting.Mode(GridSortingMode.Single))
.FilterRow(f => f.Visible(true))
.HeaderFilter(f => f.Visible(true))
.AllowColumnReordering(true)
.ShowBorders(true)
.Grouping(grouping => grouping.AutoExpandAll(true))
.SearchPanel(searchPanel => searchPanel.Visible(true))
.GroupPanel(groupPanel => groupPanel.Visible(true))
.HoverStateEnabled(true)
.ShowRowLines(true)
.RowAlternationEnabled(true)
.Scrolling(scrolling => scrolling.RowRenderingMode(GridRowRenderingMode.Virtual))
.Selection(s => s.Mode(SelectionMode.Single))
.OnSelectionChanged("gridSelectionChanged")
.OnExporting("exporting")
.OnRowUpdating("RowUpdating")
.OnEditorPreparing("onEditorPreparing")
.OnSaved("setItemTreeToTextSaving")
.OnEditingStart(#<text>
function(e) {
GetKeyId(e.key)
}
</text>)
.Editing(e => e.Mode(GridEditMode.Popup)
.AllowUpdating(false)
.AllowAdding(false)
.AllowDeleting(false)
.UseIcons(true)
.Popup(p => p
.ShowTitle(true)
.Width(700)
.Height(525)
)
.Form(f => f.Items(items =>
{
items.AddGroup()
.Caption("Detail Group Quota")
.ColCount(2)
.ColSpan(2)
.Items(groupItems =>
{
groupItems.AddSimpleFor(m => m.GroupQuotaId).Visible(false);
groupItems.AddSimpleFor(m => m.SitePlan);
groupItems.AddSimpleFor(m => m.Description);
});
items.AddGroup()
.Caption("Principal")
.ColCount(2)
.ColSpan(2)
.Items(groupItems =>
{
groupItems.AddSimpleFor(m => m.Principal).Template(new TemplateName("EmbeddedDataGridMultiple")).ColSpan(2);
});
}))
)
)

writing a script/Function for checkboxes and Custom Delete button in Telerik UI for ASP.NET MVC

I need help writing a script/Function for my Telerik UI for asp.net MVC program. I have a delete button in my tool bar and I think my script is correct for it deleting. Now, I'm told that my check boxes haft to have a script also to be deleted when checked. As a C# coder, I'm not entirely knowledgeable about Json coding. So, any help would be appreciated! Here is my code below.
#(Html.Kendo().Grid<MVCSQLDatabase.Models>()
.Name("Grid")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Batch(true)
.Model(model => model.Id(p => p.Proposal_Uid))
.Read(read => read.Action("Proposals_Read", "Grid"))
.Create(create => create.Action("Proposals_Create", "Grid"))
.Update(update => update.Action("Proposals_Update", "Grid"))
.Destroy(destroy => destroy.Action("Proposals_Destroy", "Grid"))
)
.Resizable(resize => resize.Columns(true))
.Columns(columns =>
{
columns.Select().Width(100); //<-- my check boxes code.
columns.Bound(c => c.Prime).Width(215);
columns.Bound(c => c.Proposal).Width(200);
columns.Bound(c => c.C).Width(190);
columns.Bound(c => c.Cl).Width(185);
columns.Bound(c => c.T).Width(290);
columns.Bound(c => c.M).Width(220);
columns.Bound(c => c.S).Format("{0: dd/MM/yyyy}").Width(170);
columns.Bound(c => c.E).Format("{0: dd/MM/yyyy}").Width(170);
columns.Bound(c => c.P).Width(235);
columns.Bound(c => c.Con).Width(215);
columns.Command(command => { command.Destroy(); }).Width(180);// <--- My delete button in my column
})
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
toolbar.Excel();
toolbar.Custom().Text("Delete").Name("batchDestroy").IconClass("k-icon k-i-close"); //<-- my custom made delete button in my toolbar.
})
.ColumnMenu()
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Selectable(selectable =>
{
selectable.Mode(GridSelectionMode.Multiple);
selectable.Type(GridSelectionType.Row);
})
.PersistSelection()
.Filterable(filterable => filterable.Mode(GridFilterMode.Row))
.Scrollable()
.HtmlAttributes(new { style = "height:835px;" })
)
<script>
$("#grid").on("click", "batchDestroy", function() {
var $tr = $(this).closest("tr"),
grid = $("#grid").data("kendoGrid"),
dataItem = grid.dataItem($tr);
grid.dataSource.remove(dataItem);
});
</script>
Here is the code for anybody else stuck in this situation. The thing that got me the most, was the .done function to end the button click function and then saving the grid AFTER the delete was made. Hopefully, this helps others!
<script>
$(document).ready(function ()
{
$(".k-grid-Destroy").on("click", function (e)
{
e.preventDefault();
var grid = $("#Grid").data("kendoGrid");
var selectedRows = grid.select();
kendo.confirm(kendo.format("Are you sure you wish to delete {0} records?", selectedRows.length))
.done(function ()
{
$.each(selectedRows, function (i, row)
{
grid.removeRow(row);
})
grid.saveChanges();
});
});
});
</script>

Custom Max aggregate on a Date column in kendo grid

I am trying to perform a custom max aggregate on a date column in a kendo grid and display it using the ClientFooterTemplate at the bottom of the column. I want to calculate the max aggregate only when all dates under the date column have values.
#(Html.Kendo().Grid<InstallerWrapper>().Name(#"InstallerTable")
.DataSource(dataSource => dataSource
.Ajax()
.Model(m => m.Id(o => o.InstallerId))
.Read(read => read
.Action("GetInstaller", "DataProvider", new { orderId = Model.OrderId })
.Type(HttpVerbs.Post))
.Aggregates(aggregates =>
{
aggregates.Add(o => o.SurveyReceivedDate).Max();
})
.PageSize(20)
)
.Columns(columns =>
{
columns.Bound(o => o.InstallerId).Title("Installer")
.ClientTemplate("#=VendorName#")
.Filterable(false).Width(225)
.ClientFooterTemplate("All")
.Sortable(false);
columns.Bound(o => o.SurveyReceivedDate).Title("Survey Received")
.HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" })
.Filterable(false)
.ClientTemplate("#=SurveyReceivedDate#")
.ClientFooterTemplate("#=kendo.toString(kendo.parseDate(max),'MM/dd/yyyy')#")
.Sortable(false);
})
.Selectable()
.Sortable()
.Filterable()
.Pageable(p => p.Refresh(true)))
Use a function in the ClientFooterTemplate for the column to get this.
columns.Bound(o => o.SurveyReceivedDate).Title("Survey Received").HeaderHtmlAttributes(new { style = "overflow: visible; white-space: normal" }).Filterable(false)
.ClientTemplate("#=SurveyReceivedDate#")
.ClientFooterTemplate("#if (getMaxDateText()){# #} else{# #=kendo.toString(kendo.parseDate(max),'MM/dd/yyyy')# #} #")
.FooterHtmlAttributes(new { style =" color: red "})
.Sortable(false);
Javascript Function:
<script>
function getMaxDateText() {
var surveyReceivedArray = [];
var data = $("#InstallerTable").data("kendoGrid").dataSource._data;
for (var i = 0; i < data.length; i++) {
surveyReceivedArray.push(data[i].SurveyReceivedDate);
}
var isAtLeastOneNull = surveyReceivedArray.some(function (o) { return o === null; });
if (isAtLeastOneNull) {
return true;
}
else {
return false;
}
}
</script>

How to pass object as parameter to kendo grid read method

I have kendo grid as follow.
#(Html.Kendo().Grid<ManualInputDetail>()
.Name("gManualInputDetail")
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden(true);
columns.Bound(c => c.Month).Title("Month");
columns.Bound(c => c.Value).Title("Value");
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Navigatable()
.Selectable(selectable =>
{
selectable.Mode(GridSelectionMode.Single);
selectable.Type(GridSelectionType.Row);
})
.Sortable(sortable =>
{
sortable.SortMode(GridSortMode.MultipleColumn);
})
.DataSource(dataSource => dataSource
.WebApi()
.Model(model => model.Id(p => p.Id))
.PageSize(12)
.Read(read => read.Url(Url.HttpRouteUrl("ActionApi", new { controller = "ManualInputDetails", action = "GetManualInputDetails" })).Data("getFilterData"))
)
.Pageable(p => p.Refresh(true))
)
using getFilterData function I want to pass object parameter to read method. getFilterData function as follow
function getFilterData() {
var header= {
SectorId: 1,
BrandId: 2,
LocationId: 1,
DataElementId:2
}
return {
header: header
};
}
GetManualInputDataElements method as follow
[ActionName("GetManualInputDetails")]
public DataSourceResult GetManualInputDetails([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))] DataSourceRequest request,ManualInputHeader header)
{
var model = new DataElementMgt().GetAll(header).Select(x => new DataElement()
{
Id = x.Id,
DataElementTypeId = x.DataElementTypeId,
Name = x.Name,
Descriptionn = x.Descriptionn
}).ToList().ToDataSourceResult(request);
return model;
}
In here header value always gives as null. What is the reason for that. Is any thing wrong? Please help..
change the getFilterData method to this
function getFilterData() {
var _header= {
SectorId: 1,
BrandId: 2,
LocationId: 1,
DataElementId:2
}
return {
header: _header
};
}
and it should work. dont use the same name for what you return and declare.

Error event handling causes Read to not be called

Below is my PartialView for a Kendo Grid. As of now, my Parts_Read action is NOT called. But, if I comment out
.Events(events => events.Error("error_handler"))
Then everything works fine. Any ideas of why this is happening?
#using Kendo.Mvc.UI;
#using eRPortalDashboard.Models
#model PMPartsViewModel
#{
int PMNumber = Model.PMNumber;
string uniqueName = Model.PartsGrid.ID;//Regex.Replace(Guid.NewGuid().ToString(), "[^A-Za-z]+", "");
bool enableToolbar = Model.PartsGrid.EnableToolbar;
bool enablePageable = Model.PartsGrid.Pageable;
bool enableSortable = Model.PartsGrid.Sortable;
bool enableColumnMenu = Model.PartsGrid.EnableColumnMenu;
bool enableGroupable = Model.PartsGrid.Groupable;
bool enableColumnResizing = Model.PartsGrid.AllowColumnResizing;
bool enableScrolling = Model.PartsGrid.Scrollable;
bool enableSelection = Model.PartsGrid.Selectable;
}
#(Html.Kendo().Grid<PartViewModel>()
.Name(uniqueName)
.Columns(columns =>
{
columns.Bound(c => c.ItemNumber);
columns.Bound(c => c.Description);
})
.ToolBar(toolBar =>
{
toolBar.Custom().Text("Test Button").Url("#").HtmlAttributes(new { id = "testButton" });
})
.Pageable(pager => pager
.Input(false) //Using pageable.numeric and pageable.input at the same time is not recommended.
.Numeric(true)
.Info(true)
.PreviousNext(true)
.Refresh(true)
.PageSizes(new object[] { 5, 10, 20, 50, "all" })
.Enabled(enablePageable)
)
.Selectable(s => s.Mode(mode: GridSelectionMode.Multiple).Enabled(enableSelection))
.AllowCopy(enableSelection) //selectable needs to be enabled and set to multiple
.Sortable(s => s.SortMode(GridSortMode.MultipleColumn).Enabled(enableSortable))
.ColumnMenu(c => c.Enabled(enableColumnMenu))
.Groupable(g => g.Enabled(enableGroupable))
.Scrollable(s => s.Height("auto").Enabled(enableScrolling))
.Resizable(resize => resize.Columns(enableColumnResizing))
//.Events(events => events.DataBound(uniqueName + "_updateGrid").Change(uniqueName + "_updateGrid"))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.Events(events => events.Error("error_handler"))
.Read("Parts_Read", "PM", new { PMNumber = PMNumber })
)
)
<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);
}
}
The main crux of my issue was the fact that error_handler was declared after my MVC code, thereby making it unable to bind to the method.
Apparently, with Kendo (maybe others), when using Partial Views, the javascript function must be declared BEFORE it is used in Razor syntax for that view.
see also: telerik forum post