I have the following Kendo grid:
#(Html.Kendo().Grid<Mizuho.AMS.Models.AMSServiceProcessNotificationModel>()
.Name("grd")
.ToolBar(toolBar =>
{
toolBar.Create();
})
.Sortable()
.Scrollable(a => a.Height("auto"))
.Filterable(s => s.Enabled(false))
.Selectable(s => s.Enabled(false))
.Pageable(p => p.Enabled(true).Refresh(true).PageSizes(new List<string> { "all", "10", "15", "20", "50" }))
.HtmlAttributes(new { style = "width: 100%;" })
.Editable(e => e.Mode(GridEditMode.PopUp).TemplateName("NotificationEditor").Window(w => w.Width(700)))
.Columns(columns =>
{
columns.Bound(s => s.ProcessId).Width(90);
columns.Bound(s => s.NotificationType).Width(140);
columns.Bound(s => s.NotificationAction).Width(140);
columns.Bound(s => s.Parameters).Width(680);
columns.Command(cmd => { cmd.Edit(); cmd.Destroy(); });
})
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.PageSize(15)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(s => s.ID);
})
.Read(read => read.Action("Read", "Notification"))
.Create(create => create.Action("Create", "Notification"))
.Update(update => update.Action("Update", "Notification"))
.Destroy(destroy => destroy.Action("Destroy", "Notification"))
)
.Resizable(resize => resize.Columns(true))
)
As you can see, I am using a popup dialog to edit a row. This creates a Kendo window with an update button, which will cause the Update method of the Notification controller to fire. If there is an error there, the error_handler specified above is called. This is it:
function error_handler(e) {
if (e.errors) {
var message = "";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
}
}
I display any errors, and the Kendo window is dismissed (actually, the order is, dismiss window, then errors are displayed).
What I want to do instead:
If there is an error after the user clicks the Update button, call the update method, get the error and display it, and NOT DISMISS THE WINDOW. This will allow the user to correct the error and try again.
Thanks for reading.
Related
I have a ASP.NET Core Kendo grid which display's list of Users. The grid has pouup mode editor template. The Kendo Grid code looks like this.
#(Html.Kendo().Grid<Anju.PubSTRAT.Web.Areas.Admin.Models.UserViewModel>()
.Name("UserGrid")
.Columns(columns =>
{
columns.Command(command =>
{
if (UserAccessService.CanEdit("User"))
{
command.Edit().UpdateText("Submit").Text(" ");
command.Custom("Clear").Text(" ").IconClass("k-icon k-i-clear-css k-grid-features").HtmlAttributes(new { title = "Clear User", #class = "k-grid-custom" }).Click("User_clearUser");
command.Custom("Email").Text(" ").IconClass("k-icon k-i-envelop").HtmlAttributes(new { title = "Send Welcome Email", #class = "k-grid-custom" }).Click("User_sendWelcomeEmail");
command.Custom("Unlock").Text(" ").IconClass("k-icon k-i-unlock").Visible("function (e) { return (!e.IsLockedOut); }").HtmlAttributes(new { title = "Disable User", #class = "k-grid-custom" }).Click("User_disableUser");
command.Custom("Lock").Text(" ").IconClass("k-icon k-i-lock").Visible("function (e) { return (e.IsLockedOut); }").HtmlAttributes(new { title = "Enable User", #class = "k-grid-custom" }).Click("User_enableUser");
command.Custom("UserFile").Text(" ").IconClass("k-icon k-i-file").HtmlAttributes(new { title = "User Profile File", #class = "k-grid-custom" }).Click("User_openFilePopup");
}
}).Width(75);
columns.Bound(p => p.UserId).Hidden(true);
columns.Bound(p => p.UserName).MinResizableWidth(100);
columns.Bound(p => p.Prefix).MinResizableWidth(50);
columns.Bound(p => p.FirstName).MinResizableWidth(50);
columns.Bound(p => p.LastName).MinResizableWidth(50);
columns.Bound(p => p.Suffix).MinResizableWidth(50);
columns.Bound(p => p.Email).MinResizableWidth(100);
columns.Bound(p => p.PhoneNumber).MinResizableWidth(60);
})
.ToolBar(toolbar =>
{
toolbar.Custom().Text("Reset Filters").HtmlAttributes(new { id = "resetAllGridFilters", #class = "btn-grid-toolbar", onclick = "ResetGridFilter(\"UserGrid\")" });
if (UserAccessService.CanAdd("User"))
{
toolbar.Create().Text("Add New User").HtmlAttributes(new { #class = "btn-grid-toolbar" });
}
if (UserAccessService.IsAnjuAdmin)
{
toolbar.Custom().Text("Flag Reset Security").HtmlAttributes(new { id = "flagResetSecurity",#class = "btn-grid-toolbar", onclick = "User_flagResetSecurity()" });
toolbar.Custom().Text("Unflag Reset Security").HtmlAttributes(new { id = "unFlagResetSecurity",#class = "btn-grid-toolbar", onclick = "User_unFlagResetSecurity()" });
}
toolbar.Custom().Text("Show Disabled Users").HtmlAttributes(new { id = "showHideDisabledUsers", #class = "btn-grid-toolbar", onclick = "showHideDisabledUsers()" });
})
.Pageable(pageable => pageable
.Refresh(true)
.Responsive(false)
.PageSizes(Constants.PageSizes)
.ButtonCount(5))
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.Filterable()
.Events(e => e.DataBound("gridDataBoundAutoFit"))
.Events(e => e.Edit("User_AddEditUser"))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(UserAccessService.PageSize)
.ServerOperation(true)
.Events(e => e.RequestEnd("User_AddProductDetails"))
.Events(events => events.Error("onGridError"))
.Model(model => model.Id(p => p.UserId))
.Read(read => read.Action("GetUserList", "User").Data("getUserDetailsOptions"))
.Create(create => create.Action("AddUser", "User"))
.Update(update => update.Action("UpdateUser", "User")))
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("User").Window(w => w.Height(670).Width(600)))
)
The Editor template is having tab strips and one of tab is having nested Kendo grid.
The Code for the ASP.NET Core Kendo Grid is as follows :
<script id="UserProductSegmentTemplate" type="text/kendo">
#(Html.Kendo().Grid<Anju.PubSTRAT.Web.Areas.Admin.Models.SegmentViewModel>()
.Name("UserProductSegmentGrid#=ProductId#")
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(c => c.SegmentId).Width(0).Hidden();
columns.Bound(c => c.Name).Title("Segment Name").Width(100);
})
.Sortable()
.Scrollable()
.PersistSelection()
.NoRecords(records => records.Template("No Records."))
.DataSource(dc => dc.Ajax()
.ServerOperation(true)
.Model(model => model.Id(p => p.SegmentId))
.Read(read => read.Action("GetSegmentList", "Segment", new { productId = 1 }))
)
.ToClientTemplate()
)
</script>
<div class="row">
#(Html.Kendo().Grid<Anju.PubSTRAT.Web.Areas.Admin.Models.ProductViewModel>()
.Name("ProductGrid")
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(p => p.ProductId).Hidden(true);
columns.Bound(p => p.Name).MinResizableWidth(200);
columns.Bound(p => p.Identifier).MinResizableWidth(150);
columns.Bound(p => p.GenericName).MinResizableWidth(150);
})
.Pageable(pageable => pageable
.Refresh(true)
.Responsive(true)
.PageSizes(Constants.PageSizes)
.ButtonCount(5))
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.Filterable()
.PersistSelection()
.Events(e => e.Change("onUserProductGridChange"))
.Events(e => e.DataBound("onUserProductDataBound"))
.ClientDetailTemplateId("UserProductSegmentTemplate")
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(UserAccessService.PageSize)
.ServerOperation(true)
.Model(model => model.Id(p => p.ProductId))
.Read(read => read.Action("GetProductList", "Product")))
.ToClientTemplate()
)
</div>
When I click on "Add New User" toolbar button the editor popup opens but grid is not getting rendered and getting "Invalid template" in browser console.
I'm trying to limit the dropdowns in my kendo grid to only contain Products that have been previously mapped to the company chosen in another cell in the row.
I've used a dynamic drop down editor template approach.
However, the ID passed to getCompanyId() is always null and therefore my dropdowns are always null.
View:
#(Html.Kendo().Grid<XXXAppXXX.Models.WeeklyRailPlan>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.WeekNumber);
columns.Bound(c => c.Company).ClientTemplate("#=(data.Company) ? Company.Name : 'Select Company...'#");
columns.Bound(c => c.ServiceCode);
columns.Bound(o => o.Product)
.ClientTemplate("#= (data.Product) ? Product.Name : 'Select Product'#")
.EditorTemplateName("DynamicDropDownList");
//etc
})
.ToolBar(toolbar => {
toolbar.Create();
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Filterable()
.Events(ev => ev
.Remove(#"function(e){setTimeout(function(){$('#grid').data('kendoGrid').dataSource.sync()})}")
)
.Sortable(sortable => {
sortable.SortMode(GridSortMode.SingleColumn);
})
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("error_handler"))
.Sort(p => { p.Add("WeekNumber").Descending(); })
.Model(model => model.Id(p => p.ID))
.Read(read => read.Action("WeeklyRailPlans_Read", "WeeklyRailPlanGrid"))
.Create(create => create.Action("WeeklyRailPlans_Create", "WeeklyRailPlanGrid"))
.Update(update => update.Action("WeeklyRailPlans_Update", "WeeklyRailPlanGrid"))
.Destroy(destroy => destroy.Action("WeeklyRailPlans_Destroy", "WeeklyRailPlanGrid"))
)
)
EditorTemplate called DynamicDropDownList.cshtml
<script type="text/javascript">
function getCompanyId() {
return { CompanyID: '#=ID#' };
}
</script>
#(Html.Kendo().DropDownList()
.Name("Product")
.DataValueField("ID")
.DataTextField("Name")
.DataSource(ds => ds
.Read(read => read.Action("GetProductsForCompany", "Products").Data("getCompanyId")))
)
Controller method GetProductsForCompany (this is always receiving null)
public ActionResult GetProductsForCompany(int CompanyID)
{
return Json(db.Products.Where(e => e.Companies.Any(t =>t.ID == CompanyID)), JsonRequestBehavior.AllowGet);
}
I use code like this:
<script type="text/javascript">
function getCompanyId() {
var gview = $('#grid').data("kendoGrid");
var selectedItem = gview.dataItem(gview.select());
return { CompanyID: selectedItem.ID };
}
</script>
This solution required was:
function getCompanyId() {
var grid = $('#grid').data('kendoGrid');
var dataItem = grid.dataItem(grid.table.find('.k-edit-cell').parents('tr'))
return { CompanyID: dataItem.Company.ID };
}
I have a question based on my current situation, I have a grid with ClientDetail / Child grid inside of it. In my parent grid there is a custom command button, let say...
"columns.Command(
command => { command.Custom("Edit").Click("showEdit"); command.Destroy();
}).Width(160);"
and also i had my custom command button as well in my child grid, let say...
"columns.Command(
command => { command.Custom("Edit").Click("showSubEdit"); command.Destroy();
}).Width(160);"
Those 2 custom command should call different function which is "showEdit" & "showSubEdit". The problem is, every time custom command in child grid triggered, it always calls its parent's function which is "showEdit", however the child grid should call "showSubEdit".
Is there something i missed ?
NB :
function showEdit(e) {
...
}
function showSubEdit(e) {
...
}
Grid Code :
<div>
#(Html.Kendo().Grid<ActivityModel>()
.Name("GridActivity")
.Columns(columns =>
{
//columns.Template(t => { }).Title("No").ClientTemplate("#= renderNumber(data) #").Width(50);
columns.Bound(c => c._id).Visible(false);
columns.Bound(c => c.ActivityType.TypeTitle).Title("Type").Width(80);
columns.Bound(c => c.ActivityTitle).Title("Title").Width(120);
columns.Bound(c => c.DependenciesStr).Title("Dependencies").Width(120);
columns.Bound(c => c.ResourcesStr).Title("Resources").Width(120);
columns.Bound(c => c.FromStr).Title("From");
columns.Bound(c => c.ToStr).Title("To");
columns.Bound(c => c.Status).Title("Status").Width(90).Format("{0:0.00} %").Width(85);
columns.Bound(c => c.Weight).Title("Weight").Format("{0:0.00} %").Width(85);
columns.Command(command => { command.Custom("Edit").Click("showEdit"); command.Destroy(); }).Width(160);
})
.HtmlAttributes(new { style = "height: 290px;" })
.Groupable()
.Scrollable()
.Sortable()
.Filterable()
.ClientDetailTemplateId("template")
.Pageable(x => x.PageSizes(new int[] { 10, 20 }).Refresh(true))
.Resizable(resize => resize.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Model(c => c.Id(p => p._id))
.Read(read => read.Action("ProjectActivities_Read", "Project", new { projectId = ViewBag.ProjectId }))
.Destroy(destroy => destroy.Action("ProjectActivities_Destroy", "Project", new { projectId = ViewBag.ProjectId }))
)
.Events(x => x.DataBound("resetRowNumber"))
)
</div>
<script id="template" type="text/kendo-tmpl">
#(Html.Kendo().TabStrip()
.Name("TabStrip_#=_id#")
.SelectedIndex(0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items =>
{
items.Add().Text("Sub Activity").Content(#<text>
#(Html.Kendo().Grid<ActivityModel>()
.Name("GridChild_#=_id#")
.Columns(columns =>
{
columns.Bound(x => x._id).Visible(false);
columns.Bound(x => x.ActivityType.TypeTitle).Title("Type");
columns.Bound(x => x.ActivityTitle).Title("Title").Width(150);
columns.Bound(x => x.DependenciesStr).Title("Dependencies").Width(150);
columns.Bound(x => x.ResourcesStr).Title("Resources").Width(150);
columns.Bound(x => x.FromStr).Title("From");
columns.Bound(x => x.ToStr).Title("To");
columns.Bound(x => x.Status).Title("Status").Width(90).Format("{0:0.00} %").Width(85);
columns.Bound(x => x.Weight).Title("Weight").Format("{0:0.00} %").Width(85);
columns.Command(command => { command.Custom("Edit").Click("showEditSub"); command.Destroy(); }).Width(160);
})
.Pageable(x => x.PageSizes(new int[] { 5, 10 }).Refresh(true))
.Resizable(resize => resize.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(5)
.Model(x => x.Id(y => y._id))
.Read(read => read.Action("ProjectSubActivities_Read", "Project", new { projectId = ViewBag.ProjectId, activityId = "#=_id#" }))
.Destroy(destroy => destroy.Action("ProjectSubActivities_Destroy", "Project", new { projectId = ViewBag.ProjectId, activityId = "#=_id#" }))
)
.Pageable()
.Sortable()
.ToClientTemplate())
</text>
);
}).ToClientTemplate())
</script>
I got around the bubbling by checking if the element shown by the first command event is visible:
function showDetailsLevel(e) {
e.preventDefault();
originatingId = this.dataItem($(e.currentTarget).closest("tr")).Id
var wnd = $("#Details").data("kendoWindow");
if (!$("#Details").is(":visible")) {
wnd.center();
wnd.open();
var grid = $("#DetailGrid").data("kendoGrid");
grid.dataSource.read();
}
}
I 'm working on a project and i have a problem. I decide to use kendo grid to help create grid. My grid have a field allow user to upload multiple file in each row.
I want after user upload file, file name will be asign to FileAttach column and send to server when i click save.
One more thing that those files will appear in FileAttach column with a tiny button to delete that file.
I try but it 's not work
I 'm not good at kendo tempalte and javascript so i stuck at this. Hope someone help me, it take me more than a week.
#(Html.Kendo().Grid<TamCao.Core.DomainModel.AcademicDetail>()
.Name("Academic_Grid")
.Columns(columns =>
{
columns.Bound(a => a.ID).Visible(false);
columns.Bound(a => a.PlaceName);
columns.Bound(a => a.From).Format("{0:dd/MM/yyyy}").Width(100);
columns.Bound(a => a.To).Format("{0:dd/MM/yyyy}").Width(100);
columns.Bound(a => a.Degree);
columns.Bound(a => a.DateObtained).Format("{0:dd/MM/yyyy}").Width(180);
columns.Bound(a => a.FileAttach).Template(#<Text> #= FileAttach # </Text>);
columns.Template(#<Text></Text>).ClientTemplate("<input type='file' id='uploadAcademicDetail' multiple=multiple name='uploadAcademicDetail'/>").Width(200).Title("File Attatch"); // Upload File
columns.Command(command => command.Destroy()).Width(90);
})
.ToolBar(toolBar =>
{
toolBar.Create();
toolBar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(a => a.ID);
})
.PageSize(20)
.Read(read => read.Action("AcademicDetail_Read", "AcademicExperience"))
.Create(create => create.Action("AcademicDetail_Create", "AcademicExperience"))
.Update(update => update.Action("AcademicDetail_Update", "AcademicExperience"))
.Destroy(destroy => destroy.Action("AcademicDetail_Destroy", "AcademicExperience"))
)
.Events(e =>
{
e.DataBound("AcademicDataBound");
})
)
</div>
<script type="text/javascript">
function AcademicDataBound(e)
{
$("input[type='file']").kendoUpload({
multiple: true,
async: {
saveUrl: '/AcademicExperience/UploadAcademicDetailAttach',
},
upload: function (e) {
},
success: function (e) {
var grid = $("#Academic_Grid").getKendoGrid();
alert(grid.dataItem($("FileAttach")));
}
});
}
</script>
here's my kendo grid using aspl.net mvc wrapper. the problem is when you do a batch inline editing. and click on save.
.Create(create => create.Action("UpdateLiabilities", "Liability", parameters))
will be triggered and saved all the changes into the database. now I need to added a callback function to show an account successfully added message. I am not sure how to add this callback function.
#(Html.Kendo().Grid<LiabilityVM>()
.Name("QualifiedNonrecourseDebtGrid")
.HtmlAttributes(new { style = "height: 300px;" })
.Columns(columns =>
{
columns.Bound(i => i.Id).Visible(false);
columns.Bound(i => i.AccountId).Visible(false);
columns.Bound(i => i.AccountNumber)
.Title("Account #")
.ClientTemplate("<span style='white-space:nowrap'> #= AccountNumber # </span>")
.HtmlAttributes(new { nowrap = "nowrap" })
.Width(70);
columns.Bound(i => i.Description)
.Title("Description")
.ClientTemplate("<span href='\\#' title='#= getEncodedValueOrDefault(Description, '')#' style='white-space:nowrap'>#= getHtmlEncode(Description, '') #</span>")
.HtmlAttributes(new { nowrap = "nowrap" })
.Width(120);
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.DataSource(grid => grid.Ajax()
.Batch(true)
.Model(model => {
model.Id(i => i.Id);
model.Field(p => p.AccountNumber).Editable(false);
})
.ServerOperation(true).Group(groups => groups.Add(p => p.Source))
.Create(create => create.Action("UpdateLiabilities", "Liability", parameters))
.Read(read => read.Action("GetLiabilities", "Liability", parameters))
.Update(update => update.Action("UpdateLiabilities", "Liability", parameters))
.Aggregates(aggregates =>
{
aggregates.Add(p => p.TaxAdjustmentBalance).Sum();
})
)
.Sortable()
.Filterable()
.Selectable(s => s.Mode(GridSelectionMode.Single))
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.ColumnMenu()
.Scrollable()
)
There is a special event for this called sync.
In your case it should be something like this:
.DataSource(grid => grid.Ajax().Events(ev=>ev.Sync("theNameOfTHeCallBackFUnction")))
in your UpdateLiabilities method
return jsonp instead of json ( JavaScriptResult) as
const string alertMessage = "created";
string aMessage = string.Format("alert('{0}');", alertMessage);
var returned = new JavaScriptResult { Script = aMessage };
return returned;