Kendo grid error missing when scrolling - kendo-ui

I have simple kendo grid with scrolling. It shows 20 items at the beginning and when scrolling it gets dynamically more data and add to the grid.
Normally when getting data for first page when grid is loading, when dataService throws exception like this:
return new HttpStatusCodeResult((int)HttpStatusCode.ServiceUnavailable, this.T("System Error - retrying.").Text);
and my js method binded in configuration
Events(events => events.Error("acc.mp.gridErrorDialog"))
catch it and display proper message.
The problem is with next page, when grid is getting more data.
I have seen that is happend when I toucht the scroll and scroll like 3 rows (even thought page size is 20), grid is trying to get data to the buffer to show them when I scroll 20 items.
But when error happens in this operation, the same like in first query, Kendo grid is not showing it immediately (becuse I didn't scrool yet 20 rows only it keeps its in his buffer) and nothing happen, and when I scroll to 20 rows spinner shows and all frezes. Method acc.mp.gridErrorDialog is not fired.
Grid initialization:
public static GridBuilder<T> InitializeGrid<T>(this GridBuilder<T> gridBuilder, string gridName, string dataBindAction, string controllerName, object routeValues) where T : class
{
if (gridBuilder == null)
{
throw new ArgumentNullException("gridBuilder");
}
return
gridBuilder
.Name(gridName)
.TableHtmlAttributes(new { Class = "styled", cellpadding = "0", border = "0", margin = "0" })
.HtmlAttributes(new { Class = "dynamicGridHeight" })
.AutoBind(false)
.DataSource(
dataSource =>
dataSource.Ajax()
.PageSize(ModelPortfolioConfigurationManager.GridPageSize)
.ServerOperation(true)
.Events(events => events.Error("acc.mp.gridErrorDialog"))
.Read(read => read.Action(dataBindAction, controllerName, AddAntispinnerParameter(routeValues))));
}
and grid:
#(Html.Kendo()
.Grid<ValidatedClientAccountViewModel>()
.InitializeGrid(Naming.GridId(GridType.Upper), "GetClients, "ModelClients", new { modelTemplateId = Model.ModelId })
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(o => o.AccountId)))
.ToolBar(toolBar => toolBar.Template(
#<text>
<script type="text/javascript">
acc.mp.utils.bindLiveSearch($("##Naming.GridId(GridType.Upper) input[name='txtSearch']"), function () { $("##Naming.GridId(GridType.Upper) button[name='btnSearch']").click(); });
acc.mp.utils.searchGridFocus($("##Naming.GridId(GridType.Upper) input[name='txtSearch']"));
</script>
</text>))
.Columns(columns =>
{
columns.Bound(o => o.AccountId)
.ClientTemplate(ClientTemplates.UpperGridRowSelection)
.HtmlAttributes(new { style = "text-align: center" })
.HeaderTemplate(ClientTemplates.SelectAllCheckBox("cbLinkAll"))
.HeaderHtmlAttributes(new { style = "text-align: center" })
.Filterable(true)
.Sortable(false)
.Width(35);
columns.Bound(o => o.ClientReferenceNumber).Title(accountReference).HeaderHtmlAttributes(new { title = accountReference });
})
.EnableScrollingAndPaging(ModelPortfolioConfigurationManager.GridPageSize)
.Sortable()
.Events(events =>
{
events.DataBinding("acc.mp.clientAccounts.upperGrid.dataBinding");
events.DataBound("acc.mp.clientAccounts.upperGrid.dataBound");
events.Change("acc.mp.clientAccounts.upperGrid.rowSelect");
})
)

this is a bug in kendo, You can track the status of the issue here https://github.com/telerik/kendo-ui-core/issues/749

Related

Pass values of kendo grid to popup window

I have implemented a kendo grid and context menu in my MVC5 page. I open a window on click of the Update Status menu. I need to retrieve the requestid and couple of other fields from the selected row in the pop up window. I would also need to show a drop down control with values. Whats the best way of doing it
Grid
div class="requestgrid" id="requestGrid">
#(Html.Kendo().Grid<CC.GRP.MCRequest.ViewModels.RequestViewModel>()
.Name("GridRequest")
.Columns(columns => {
columns.Bound(o => o.RequestID).Width("100px");
columns.Bound(o => o.CountryCode).Width("100px");
columns.Bound(o => o.SalesOffice).Width("100px");
columns.Bound(o => o.CustomerNumber).Width("120px");
columns.Bound(o => o.ProjectName).Width("120px");
columns.Bound(o => o.ProjectContent).Width("120px");
columns.Bound(o => o.ContractStartDate).Width("140px");
columns.Bound(o => o.Priority).Width("120px");
columns.Bound(o => o.NameOfResponsiblePerson).Width("170px");
columns.Bound(o => o.Status).Width("100px");
columns.Bound(o => o.CreatedBy).Width("110px");
columns.Bound(o => o.CreatedDate).Width("110px");
columns.Bound(o => o.ModifiedBy).Width("110px");
})
//.ToolBar(toolbar => toolbar.Create())
//.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Pageable()
.Sortable()
.Filterable()
.Scrollable()
.Groupable()
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single)
.Type(GridSelectionType.Row))
.Events(events => events
.Change("onChange")
)
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(t => t.RequestID))
//.Create(update => update.Action("Team_Create", "Admin"))
.Read(read => read.Action("Requests_Read", "Request"))
//.Update(update => update.Action("Team_Update", "Admin"))
)
)
Context Menu
#(Html.Kendo().ContextMenu()
.Name("RequestMenu")
.Target("#GridRequest")
.Filter("tr")
.Orientation(ContextMenuOrientation.Vertical)
.Animation(animation =>
{
animation.Open(open =>
{
open.Fade(FadeDirection.In);
open.Duration(500);
});
})
.Items(items =>
{
items.Add()
.Text("Edit");
items.Add()
.Text("Update Status");
})
.Events(e =>
{
e.Select("onSelect");
})
)
Javascript
function onSelect(e) {
var grid = $("#GridTeam").data("kendoGrid");
var requestId;
switch ($(e.item).children(".k-link").text()) {
case "Edit":
var grid = $("#GridRequest").data("kendoGrid");
var column = grid.columns[0];
var selectedBackup = grid.dataItem(grid.select());
requestId = selectedBackup.id;
window.location.href = '#Url.Action("EditRequest", "Request", new { id = "_id_", status="Edit" })'.replace('_id_', requestId);
break;
case "Update Status":
//alert("Work in progress");
//$('#window1').data('kendoWindow').center().open();
var myWindow = $("#window");
//e.preventDefault();
//var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
//kendo.bind($("#window"), dataItem);
myWindow.kendoWindow({
width: "400px",
height: "180px",
title: "Update Request Status",
modal: true,
visible: false,
actions: ["Minimize", "Maximize", "Close"],
}).data("kendoWindow");
myWindow.data("kendoWindow").center().open();
}
You're doing it almost right, only by two details:
If you bind the contextMenu's target to the grid's container, you'll never be sure which row user did clicked. I suggest you to bind to your grid's rows(TR) instead, e.g. #GridRequest tbody tr;
I'm afraid e.currentTarget doesn't exists or returns undefined in that context. You should use e.target which will point to the clicked row if you did what I suggested above. Then you could get your dataItem as follows:
grid.dataItem(e.target);
Check out this demo with my suggestions working.

how to insert value into the kendo combo box

If I have a kendo combobox that contains more than 1 value I would like to insert "-ALL- as the DataTextField and "9999" as the DataValueField. Currently, if I have only a single record I use the DataBound event to test for that and if it = 1 then I load a grid based on this value, but if the length > 1 then I would like to add the -All-. I don't understand the insert as described by telerik.
#(Html.Kendo().ComboBox()
.Name("FAList")
.Placeholder("Select Fiscal Agency...")
.DataTextField("Text")
.DataValueField("Value")
.HtmlAttributes(new { style = "width:50%;" })
.Filter("startswith")
.AutoBind(true)
.MinLength(3)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUserAgencyList", "Entities");
})
.ServerFiltering(true);
})
.Events(e => e
.Change("onFAChange")
.DataBound("onFADataBound")
)
)
and then the function for binding the data
function onFADataBound(e) {
// the agency list dropdown
var combobox = $("#FAList").data("kendoComboBox");
// if there is only a single record then set that in the combobox and load the grid based on that
if (e.sender.dataSource.view().length == 1) {
e.sender.select(0);
var filter = this.value();
$.get('/City/CityGrid_Read', { id: filter }, function (data) {
var grid = $("#FollowUpGrid").data("kendoGrid");
grid.dataSource.read();
})
}
if (e.sender.dataSource.view().length > 1) {
}
}
Answered at: Adding an item dynamically in kendo combobox
Combining that with your code:
if (e.sender.dataSource.view().length > 1) {
$("#FAList").data("kendoComboBox").dataSource.add({ Text: "-All-",
Value: "0" });
}
Something like that! I hope you get this implemented :)
An alternative could be to change the Placeholder text in this event method where length > 1
as per example on: http://www.telerik.com/forums/placeholder-text
$("#FAList").data("kendoComboBox").input.attr("placeholder", "-All-");

How to prevent deleting items in KendoUI multiselect?

I use a Kendo.UI MultiSelect in MVC
#(Html.Kendo().MultiSelect()
.Name("ADGroups")
.DataTextField("Name")
.DataValueField("Value")
.MinLength(3)
.Value(Model.SelectedADGroups)
.HtmlAttributes(new { style = "width:auto", id="ADGroupsList" })
.Filter(FilterType.Contains)
.DataSource(source => source.Read(read => read.Action("GetADGroups", "Edit"))
.ServerFiltering(true))
.Events(e => e.Change("onChange").DataBound("onDataBound"))
)
And now I would like to prevent from deleting some Items.
So I save the current values on DataBound-Event
function saveCurrent(multi)
{
multi._savedValues = multi.value().slice(0);
multi._savedItems = multi._dataItems.slice(0);
}
function onDataBound()
{
saveCurrent(this);
}
And OnChange I detect the difference between before and after.
function onChange()
{
var previous = this._savedValues;
var current = this.value();
if (current.length < previous.length)
{
var diff = $(previous).not(current).get(0);
if (confirm('Sure?'))
{
// do nothing value already deleted
}
else
{
// reset
this.value(previous);
}
}
saveCurrent(this);
}
This works perfectly. But If I type a new phrase so the widget calls the Read-Action to add some Items all works fine and NOW when I delete an item and cancel this action, however items will be removed.
What is wrong?

How can i highlight the Kendo grid cell by color change after update

I am using Kendo Ui Grid with MVC and SignalR. I can successfully perform the CRUD operations on grid using SignalR. I would like to notify clients by highlighting(By changing cell color) the updated cell. How can I achieve this with the following code:
#(Html.Kendo().Grid<Webapplication1.Models.ShipViewModel>()
.Name("ShipGrid")
.Columns(c =>{
c.Bound(m => m.Id).Hidden();
c.Bound(m => m.LocationViewModel)
.Title("Location1");
c.Bound(m => m.Location2ViewModel)
.Title("Location2");
c.Bound(m => m.boxSent);
c.Command(p =>
{
p.Edit().Text(" ").UpdateText(" ").CancelText(" ");
p.Destroy().Text(" ").HtmlAttributes(new { #title = "Cancel" });
});
})
.ToolBar(toolbar =>
{
toolbar.Create().Text("").HtmlAttributes(new { #title = "Add" });
})
.Editable(editable => editable
.DisplayDeleteConfirmation("DELETE.")
.Mode(Kendo.Mvc.UI.GridEditMode.PopUp)
.TemplateName("abcEditor")
)
.Events(events =>
{
events.Edit("edit");
})
.DataSource(dataSource => dataSource
.SignalR()
.Transport(tr => tr
.Promise("hubStart")
.Hub("mainHub")
.Client(c => c.Read("abc_Read").Create("abc_Insert").Update("abc_Update").Destroy("abc_Delete"))
.Server(s => s.Read("abc_Read").Create("abc_Insert").Update("abc_Update").Destroy("abc_Delete")))
.Schema(schema => schema
.Model(m => {
m.Id(p => p.Id);
m.Field(p => p.Location1ViewModel).DefaultValue(ViewData["DefaultLocation1"] as Webapplication1.Models.Location1ViewModel);
m.Field(p => p.Location2ViewModel).DefaultValue(ViewData["DefaultLocation2"] as Webapplication1.Models.DeliveryLocationViewModel);
})
)
)
)
I would like to Highlight the cell that is being updating here. Something like stock market data flashing. How can I achieve this?
I've done similar kind of thing. I don't know if that helps you. In your default view model add a extra property, say "Updated" as a boolean. Now every time you have update a row, put "Updated" as a true.
And in kendo grid add a new dataBound event.
.Events(events => events.DataBound("onDataBound"))
Now on JS use something like the following;
function onDataBound(arg) {
var itemsInActivityGrid = $("#ShippingGrid").data().kendoGrid.dataSource.data().length;
for (i = 0; i < itemsInActivityGrid; i++) {
if ($("#ShippingGrid").data().kendoGrid.dataSource.data()[i].Updated == true) {
$("#ShippingGrid .k-grid-content tr[data-uid='" + $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].uid + "']").css("background-color", "orange");
}
}
}
Update: I don't know your logic. As far as you put on comments, you want to do something like online share dealing sites. Anyway, as far as I could, if you want to highlight individual cell in a row, add another extra field say "Column" along with "Updated"; it could be a string. Here you mark which cell you want to put the back ground colour from the backend. Say we've got it's value as "2".
for (i = 0; i < itemsInActivityGrid; i++)
{
var TableUID = $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].uid;
var TableToColour = $("#ShippingGrid .k-grid-content tr[data-uid='" + TableUID + "']").parent().parent()[0];
var ColumnToColor = $("#ShippingGrid").data().kendoGrid.dataSource.data()[i].Column;
$(TableToColour.rows[0].cells[" + ColumnToColor + "]).select().attr("style","background-color:blue")
}
In case, you need to highlight multiple cells on the same row, in Column send something like "1,2,3,5"; where 1, 2, 3 and 5 represents the column numbers on the same row. And after ColumnToColor do some string parsing, put it into a for loop or something and colour;
Hope this helps. Thank you.
I have achieved this as below and its working fine:
in my .cshtml page
myHub.client.highlightRow = function (id) {
var data = $("#MyGrid").data("kendoGrid").dataSource.data();
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
if (dataItem.id == id) {
//alert(dataItem.uid);
$("#MyGrid").data("kendoGrid").tbody.find("tr[data-uid=" + dataItem.uid + "]").effect("highlight", { color: "#f35800" }, 3000);
}
}
};
And in my update/insert method in my SignalR Hub class:
Clients.Others.highlightRow(mygridViewModel.Id);

Kendo grid update - update click of any row shows 1st row details

I am facing an issue with Kendo grid inline editing, The issue is even though I update any row, 1st row data is displayed in grid, Any help on this?
Before update
After update.
Interestingly the object I return from the controller does have the correct data
Controller code
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
[ActionSessionState(System.Web.SessionState.SessionStateBehavior.Required)]
[OutputCache(Duration = 0, VaryByParam = "none")]
public ActionResult _SaveBatchEditingintegrate([DataSourceRequest] DataSourceRequest request)
{
var UPObj = SessionFacade.UserProfile as UserProfile;
try
{
IntegrationRate objInteg = new IntegrationRate();
TryUpdateModel(objInteg);
if (objInteg.PeriodID != 0)
{
var Integrationrate = (from p in _draftManagecompany.IntegrationRates where p.PeriodID == objInteg.PeriodID select p).First();
TryUpdateModel(Integrationrate);
if (Integrationrate.Rate > 100) //set 100 as default
{
Integrationrate.Rate = 100;
}
}
LoadResourceJSArray();
}
catch (Exception ex)
{
// Adding related additional information along with exception object
//ExceptionLogger.Log(ex, "Period ID", id);
ExceptionLogger.Log(ex, "User Profile Info", UPObj);
// Handle exception with BubbleExceptionPolicy
if (exManager.HandleException(ex, "BubbleExceptionPolicy"))
throw; // Not to include the ex, as the previous stack trace to be maintained
}
//_draftManagecompany.IntegrationRates contains updated value in the correct order
return Json(_draftManagecompany.IntegrationRates.ToDataSourceResult(request));
}
cshtml code:
#{ var integrateGrid = Html.Kendo()
.Grid(Model.Company.IntegrationRates)
.Name("Gridintegrate")
.EnableCustomBinding(true) // Enable custom binding
.BindTo(Model.Company.IntegrationRates)
.Events(events =>
{
events.Change("DataBound_Integ");
})
.ToolBar(
commands =>
{
//commands.Insert().ButtonType(GridButtonType.BareImage).ImageHtmlAttributes(new { style = "visibility:hidden" });
}
)
.Columns(columns =>
{
columns.Bound(p => p.PeriodID).Visible(false);
columns.Bound(p => p.Month).Width(150);
columns.Bound(p => p.Rate).Format("{0:0.00}%").Width(100);
columns.Command(commands =>
{
commands.Edit().HtmlAttributes(new { #id = "btn_IntRateEdit" });
}).Width(150).Title(gridTitle);
})
.HtmlAttributes(new { style = "height: 380px;" })
.Scrollable()
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource.Ajax()
//.Batch(true)
.Read(read => read.Action("_AjaxBindingintegrate", "Company"))
.Update(update => update.Action("_SaveBatchEditingintegrate", "Company"))
.Model(model =>
{
model.Id(c => c.PeriodID);
model.Field(c => c.Month).Editable(false);
}
)
.Events(events =>
{
events.Error("CheckSessionExistsOnTelerik");
})
);
//.Pageable(paging => paging.Style(GridPagerStyles.NextPreviousAndNumeric | GridPagerStyles.PageSizeDropDown).PageSize(20, new int[3] { 20, 50, 100 })).ToComponent();
var culture = System.Globalization.CultureInfo.InvariantCulture;
//integrateGrid.Localization = new GridControlLocalization(culture);
integrateGrid.Render();
}
I think I see the problem here. From what I can tell when you complete the update you are returning the entire data set back on the update ie June, january, February etc.
On the update all you have to do is return the item you have updated back to the grid
So in your example change the return json to the following:
Return json(new { IntegrationRate}.toDataSourceResult(request,modelState),jsonbehaviour.allowget);
This then should sort out your issue.
Because you are returning the entire data set back it is rendering the first row as the expected result.
As you say you see the data saving correctly behind the scenes. So you know an error is not being thrown.

Resources