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

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.

Related

Kendo Schedule DataSource not able to get data from Controller

We are using Kendo-Scheduler in an Asp.net application.
We are having a problem getting events to display in the calendar.
When we use Server Binding, we can see the events display in the calendar as expected. We do this in our ViewComponent:
public async Task<IViewComponentResult> InvokeAsync()
{
List<TaskViewModel> myTasks = GetItems();
return View(myTasks); //these events display on the calendar succssfully
}
However, we need to use Ajax Binding. When we do the following, no data is returned to the DataSource. When we look at scheduler_dataBound() for the data, we can see that no data is returned from the controller.
What am I doing wrong in the below? Why is the Server binding working but not the Ajax Binding?
//my.cshtml
#(Html.Kendo().Scheduler<Plantview.Core.ViewModels.TaskViewModel>()
.Name("scheduler")
.Date(new DateTime(2022, 10, 01))
.StartTime(new DateTime(2022, 10, 01, 7, 00, 00))
.Height(600)
.Views(views =>
{
views.MonthView(m => {
m.Selected(true);
m.EventHeight(150);
});
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Model(m =>
{
m.Field(f => f.OwnerID).DefaultValue(1);
m.Field(f => f.Title).DefaultValue("No title");
m.Field(f => f.Description).DefaultValue("no desc");
m.RecurrenceId(f => f.RecurrenceID);
})
.Read("Read", "MyController")
)
.Events(e => {
e.DataBound("scheduler_dataBound");
})
)
<script type="text/javascript">
function scheduler_dataBound(e) {
var data = $("#scheduler").data("kendoScheduler").dataSource;
console.log(data); //Here -> _total=0 and _data has no objects
}
</script>
//My Controller method
public virtual JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
//This is getting called from calendar datasource read
return Json(GetItems().ToDataSourceResult(request)); //Here I am mocking up data
}
//My Mock data
public List<TaskViewModel> GetItems()
{
List<TaskViewModel> list = new List<TaskViewModel>();
list.Add(new TaskViewModel
{
Title = "Event 1",
Start = new DateTime(2022, 10, 1),
End = new DateTime(2022, 10, 1),
Description = "Description 1",
IsAllDay = false,
OwnerID = 1,
TaskID = 1
});
......More data
return list;
}

Cascading drop down menu with editor template kendo grid mvc

I trying to implement a cascading down list with editor template i am not sure if kendo support it, i have a grid when in editing move i am trying to filter data base on select data from an editor template
grid is showing availablity time a user can work
e.g column Timefrom, TimeTo, status, could be the following
1.) availablity
2.) Unavailablity
3.) Holiday
availablity have different time template compare to Holiday and unavailablity
e.g
"Early/day" - 07.00 -18.00
"Long day" - 0700 - 22.30
"Late" - 12.00 - 22.00
"Night" - 19.00 - 21.00
"Twilight" - 18.00 - 04.00
Holiday/Unavailablity - half day morning
holiday/Unavailablity - half day afternoon
holiday/Unavailablity - evening
holiday/Unavailablity - whole day
what i want to achive when user click on edit mode, status column have a drop down with [Availablity - Unavilablity - Holiday ] after selecting the option availablity time template will be enable with the respective time template.
example when user click on Holiday drop down in edit mode only these option should be display on availablity Time Template column ("Early/day","Long day","Late","Night","Twilight")
below is a demo code simmilar concept to the main application Thanks
main page
#(Html.Kendo().Grid<Availablity>()
.Name("grid-availablity")
.Columns(columns =>
{
columns.Bound(c => c.Id);
columns.Bound(c => c.TimeFrom);
columns.Bound(c => c.TimeTo);
columns.Bound(c => c.Status);
columns.Bound(c => c.AvailablityTimeTemplate); // only testing purpose
columns.Command(command =>
{
command.Edit();
});
})
.DataSource(databinding => databinding.Ajax().PageSize(10).ServerOperation(false)
.Model(model => model.Id(availablity => availablity.Id))
.Read("GetAvailablityList","Availability")
.Update("Availablity_Update","Availability")
)
)
<script>
function filterTimeTemplate() {
return {
AvailablityTimeTemplate: $("#AvailablityTimeTemplate").val()
};
}
</script>
Editor Template
Status Template
#(Html.Kendo().DropDownList()
.Name("Status")
//.DataTextField("")
//.DataValueField("Id")
.OptionLabel("Change Status")
.BindTo(Enum.GetNames(typeof(Status)).ToList())
)
Time Template
#(Html.Kendo().DropDownList()
.Name("AvailablityTimeTemplate")
.HtmlAttributes(new { style = "width:300px" })
.OptionLabel("Change Time...")
//.DataTextField("")
// .DataValueField("")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadingData", "Availability")
.Data("filterTimeTemplate");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("Status")
)
classes and enum
public class Availablity
{
public string Id { get; set; }
public string TimeFrom { get; set; }
public string TimeTo { get; set; }
[UIHint("AvailablityStatus")]
public Status Status { get; set; }
[UIHint("TimeTemplate")]
public string AvailablityTimeTemplate { get; set; }
public List<Availablity> GetAvailablity()
{
return new List<Availablity>()
{
new Availablity(){ Id="001", TimeFrom="0700", TimeTo="18.00", Status=Status.Available},
new Availablity(){ Id="002", TimeFrom="0700", TimeTo="23.30", Status=Status.Available},
new Availablity(){ Id="002", TimeFrom="12.00", TimeTo="22.00", Status=Status.Available}
};
}
public List<string> GetTimeTemplateList(Status status)
{
List<string> TimeTemplateCollection = null;
if (status == Status.Available) {
TimeTemplateCollection = new List<string>(){
"Long day","Late","Night","Twilight"
};
} else {
TimeTemplateCollection = new List<string>(){
"Morning Half Day","Afternoon - Half Day ","Night","Whole Day"
};
}
return TimeTemplateCollection;
}
}
public enum Status
{
Available = 0,
UnAvailable = 1,
Holiday = 2
}
controller
public JsonResult GetCascadingData(Status availablityStatus)
{
var availablity = new Availablity();
var data = availablity.GetTimeTemplateList(availablityStatus);
return Json(data, JsonRequestBehavior.AllowGet);
}
public JsonResult GetAvailablityList([DataSourceRequest] DataSourceRequest request)
{
var availablity = new Availablity();
var data = availablity.GetAvailablity();
return Json(data.AsQueryable().ToDataSourceResult(request));
}
As your comment explain further, this is what you need to change
Time Template
#(Html.Kendo().DropDownList()
.Name("AvailablityTimeTemplate")
.HtmlAttributes(new { style = "width:300px" })
.OptionLabel("Change Time...")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadingData", "Availability").Data("filterTimeTemplate");
})
.ServerFiltering(true);
})
//.Enable(false) should be removed
.AutoBind(false)
.CascadeFrom("Status")
)

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?

Kendo grid error missing when scrolling

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

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);

Resources