pass view data to custom editor in kendo grid - kendo-ui

I'm looking at an example form the demo website of kendo
http://demos.kendoui.com/web/grid/editing-custom.html
In the asp mvc code sample there is absolutely no reference to ViewData["categories"] from the controller.
Which black magic is it using to get this data in a dropdownlist in the editor?

here as shown in below section they are providing datasource path direct to database and it fetches the value from the database so no magic there everything is using basic code laungage
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Categories"
}
}
and for MVC
var categories = dataContext.Categories
.Select(c => new ClientCategoryViewModel {
CategoryID = c.CategoryID,
CategoryName = c.CategoryName
})
.OrderBy(e => e.CategoryName);
ViewData["categories"] = categories;
ViewData["defaultCategory"] = categories.First();
and for MVC view :-
.Model(model =>
{
model.Id(p => p.ProductID);
model.Field(p => p.ProductID).Editable(false);
model.Field(p => p.Category).DefaultValue(
ViewData["defaultCategory"] as Kendo.Mvc.Examples.Models.ClientCategoryViewModel);
})

Related

Get dataitem in transport.read.data() function from kendo Dropdownlist inline editor on a grid

I have a kendo dropdownlist on a Kendo grid (more specifically, it is using the Telerik MVC wrappers). When the "Edit" button is clicked on the row for the grid, the dropdownlist gets its data from an ajax jsonresult DataSource in my controller. I want to pass an Id to this datasource method so I can filter the results based on this id. However, this ID exists against the row in the table which contains the inline dropdownlist editor.
I'm looking to get the dataItem of the row which contains the dropdownlist through it's transport.read.data() function. I passed in e as a parameter to the function, but it doesn't seem to contain anything useful like e.sender. The this object doesn't reference the element, therefore I can't seem to use it for anything useful either. The best I've done so far is to get a reference to the grid (so I have access to the grid.dataItem function, but I can't pass anything meaningful into it to get the dataItem of the currently active row.
Here's a simplified version of the grid, excluding other unnecessary fields, etc.
#(Html.Kendo().Grid<Grants.ViewModels.ScheduleOfWorkItemViewModel>()
.Name("NewScheduleOfWorkItems")
.Columns(columns =>
{
columns.Bound(col => col.ScheduleOfWorkItemID).Visible(false);
columns.Bound(col => col.PercentageItemComplete).HtmlAttributes(new { #class = "cell-percentage-item-complete" }).Title("% Comp").Width(100).Format("{0:P2}").EditorTemplateName("SORREFPercentageItemComplete");
columns.Command(commandCol =>
{
commandCol.Edit();
commandCol.Destroy();
}).Width(100);
})
.Sortable()
.Pageable(pageable => pageable.Refresh(true).PageSizes(new List<object> { 10, 20, "all" }).ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Create(create => create.Action("Add_ScheduleOfWorkItem", "ScheduleOfWork"))
.Update(create => create.Action("Add_ScheduleOfWorkItem", "ScheduleOfWork"))
.Read(read => read.Action("GetScheduleOfWorkItems", "ScheduleOfWork").Data("GetIDForGetScheduleWorkItems"))
.Model(model =>
{
model.Id(c => c.ScheduleOfWorkItemID);
model.Field(c => c.ConcatenatedRenderedDescription).Editable(false);
model.Field(c => c.UnitTypeName).Editable(false);
model.Field(c => c.Cost).Editable(false);
model.Field(c => c.AdjustedTotal).Editable(false);
})
.Destroy(delete => delete.Action("RemoveScheduleItemFromScheduleOfWork", "ScheduleOfWork"))
.Sort(sort => sort.Add("ScheduleItemOrderNo").Ascending()) // <-- initial sort expression
)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Events(events =>
{
events.Edit("onSORREFEdit");
events.Save("onSORREFSave");
events.DataBound("onSORREFDataBound");
})
)
Here's the Dropdown list editor template
#(Html.Kendo().DropDownList()
.Name("SORREFPercentageItemCompleteId")
.DataTextField("PercentageGrantItemCompleteText")
.DataValueField("PercentageGrantItemCompleteId")
.DataSource(source => {
source.Read(read =>
{
read.Action("GetPercentageGrantItemCompleteLookups", "ScheduleOfWork").Data("SORREFPercentageItemCompleteData");
});
})
.HtmlAttributes(new { style = "width: 100%" })
.OptionLabel("Percentage complete...")
.Events(events =>
{
events.Select("onSORREFPercentageItemCompleteSelect");
})
)
and here's my JS function for returning data, so far, which doesn't work.
var SORREFPercentageItemCompleteData = function (e) {
var $tr = $($(this)[0].element).closest("tr"); // "this" is useless? - how can i get my tr?
var grid = $("#NewScheduleOfWorkItems").data("kendoGrid"); // grid id ok
var dataItem = grid.dataItem($tr);
return { scheduleOfWorkItemId: dataItem.ScheduleOfWorkItemID };
}
Change the dropDownList dataSource transport read from a URL string to a configuration item that contains
the URL
a custom container field that refers to the edit row container
the data item as a function that returns the additional parameters for the URL
the function will use the container to find the row to find the grid and the rows model ID value
The following code is in dojo https://dojo.telerik.com/#RichardAD/uZIguWAn which is based on demo https://demos.telerik.com/kendo-ui/grid/editing-custom.
The end-game is that the drop down ajax data query will contain the extra parameter productID = productID of row selected
function categoryDropDownEditor(container, options) {
$('<input required name="' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
autoBind: false,
dataTextField: "CategoryName",
dataValueField: "CategoryID",
dataSource: {
type: "odata",
transport: {
// originally
// read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
// magical tweakage
read:
{
container: container, // make container available to data function
url: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
// see API documentation for transport.read.data
// https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/configuration/transport.read#transport.read.data
, data: function (e) {
grid = this.container.closest(".k-grid").data("kendoGrid");
rowuid = this.container.closest("tr").data("uid");
rowIdField = grid.dataSource.options.schema.model.id;
result = {};
result [rowIdField] = grid.dataSource.getByUid(rowuid)[rowIdField];
return result;
}
}
What I do for this case is just use the Edit event of the grid.
When the user goes and tries to edit a row the event will give you the id you want.
Pass it to a global variable in your js like
var selectedRowId = // the row id
and add this parameter to be returned on your dropdownlist read.
return { scheduleOfWorkItemId: selectedRowId };
I know it is not the most elegant solution but it has worked for me and I believe is quite easy.

Post kendo grid values

Below is the Kendo grid
#(Html.Kendo().Grid<CS.Web.Models.People.GroupDetailModel>()
.Name("Grid")
.Events(e => e.DataBound("LineItems_Databound"))
.HtmlAttributes(new { style = "overflow:hidden;", #class = "normalgrid" })
.Columns(columns =>
{
columns.Bound(p => p.GroupID).Hidden();
columns.Bound(p => p.GroupName).Title("Group Name").Width(30);
columns.Bound(p => p.Department).Title("Department Name").Width(30);
columns.Bound(p => p.IsBlindSettingsEnable).Title("Blind Group")
.ClientTemplate("<input type=\"checkbox\" #= IsBlindSettingsEnable ? \"checked=checked\": \"\" # enabled=\"enabled\" />")
.Width(30);
columns.Bound("Department").Title("Remove")
.ClientTemplate("<a href='javascript:void(0)' Title='Remove' onclick='return removeUserGroupRelation(+#=GroupID#+);'> <img alt='Remove' src='" + #Url.Content("~/Content/Images/delete_icon.png") + "' /></a>")
.Width(30);
})
.Sortable()
.Scrollable(scrollable => scrollable.Virtual(false))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("getAssignedGroups", "People")
.Data("setRoutesValues")
)
//new { MerchantId = ViewBag.MerchantId, StartDate = Model.StartDate, EndDate = Model.EndDate }
)
.TableHtmlAttributes(new { #class = "grid_1" })
)
Below is the javascript code
var userID = '#ViewBag.UserID'
$.ajax({
url: '#Url.Action("SaveGroupsUserDetails")',
type: "POST",
dataType: "json",
data: { models: kendo.stringify($("#Grid").data("kendoGrid").dataSource.view()), UserID: userID },
success: function (result) {
}
});
Here in my kendo grid there is checkbox column.When i check or uncheck checkbox at CLIENT sied(in browser).And Do post via give javascript $.ajax post,it will not post the values of checkboxes which I have changed on client browser,it shows the values which it was binded from server side.
so,my question is to I want updated values to post on server which are modified on client browser.
I shall be very thankfull if you provide me answer.
You should just update your datasource on checkbox checked :
...
.ClientTemplate("<input type=\"checkbox\" #= IsBlindSettingsEnable ? \"checked=checked\": \"\" # enabled=\"enabled\" onclick='setChecked(this)' />")
...
function setChecked(cb) {
var row = $(cb).closest("tr");
var item = grid.dataItem(row);
item.IsBlindSettingsEnable = cb.checked;
}
and now your datasource is synced with the view
I believe this is because your looking at the actual value of the dataSource and not the grid itself. Your grid is non-editable. You are manually throwing the inputs into your grid and these will not effect the dataSource.
You can take two approaches do this kind of update.
You can leave the grid the way you have it set up and handle this update solely though Java Script.
To do this you will need to look up all the dataItems you need to update manually with JQuery.
You can lookup all of your check boxes with in that grid that are check, then get the relevant dataItem manually. Here is a short example showing how to get a dataItem from a row in the grid.
//checkbox is a JQuery object referencing one of your checkboxes
var row = $(checkbox).closest("tr");
var grid = $("#grid").data("kendoGrid");
var data = grid.dataItem(row);
Once you have all of your dataItems that are relevant you can then post your update. You would then have to reload your grid to get the updated status of these items.
Overall this is not the preferred way to do this kind of update with a kendo grid.
I suggest this second method.
This is the site where I will be pulling examples from: http://demos.telerik.com/aspnet-mvc/grid/editing
First you will need to make your kendo grid editable .Editable(editable => editable.Mode(GridEditMode.InCell)). You will not need the custom template that adds the checkbox anymore. It will automatically add them when you are editing your grid now.
You will need to then set the datasource to have an update function and have your server expect this update.
Your dataSource binding
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Read("Editing_Read", "Grid")
.Update("Editing_Update", "Grid")
)
And your server side code
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Editing_Update([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ProductViewModel> products)
{
if (products != null && ModelState.IsValid)
{
foreach (var product in products)
{
productService.Update(product);
}
}
return Json(products.ToDataSourceResult(request, ModelState));
}
By returning this Json object your grid will auto update to the new values. This is the preferred way to edit a grid.

Kendo Grid EditorTemplateName DropDownList Id Not Posting

I have a simple kendo grid that I am trying to associate an editor template with. The foreign key is the only property that is sent down to the client so I can't give the editor template a model type of the foreign key property.
Configuration for Kendo Grid
protected override void Configure(GridBuilder<AreaModel> grid)
{
grid.Columns(c =>
{
c.Bound(a => a.Description);
c.Bound(p => p.CompanyId).ClientTemplate("#= CompanyDescription#").EditorTemplateName("DropDown/CompanyId").Width(160);
c.Command(command => command.Edit()).Width(200);
c.Command(command => command.Destroy()).Width(110);
});
grid.ToolBar(toolbar => toolbar.Create().Text("New Area"));
grid.Editable(edit => edit.Mode(GridEditMode.InLine));
grid.DataSource(d => d
.Ajax()
.Model(m => m.Id(p => p.Id))
.Create("GridInsert", "Area")
.Update("GridUpdate", "Area")
.Destroy("GridDelete", "Area"));
}
}
The editor template is straight forward as well. Everything works except that the value is not posted to the server.
#using Kendo.Mvc.UI
#(Html.Kendo().DropDownList()
.Name("CompanyId")
.DataValueField("Id")
.DataTextField("Name")
.DataSource(d => d.Read("CompaniesData", "Company")))
Can anybody help me out on this one?
modelview propoerty name which should maintain dropdownlist's selected value must be the Name of dropdownlist in editorTemplate and the type of datavaluefield and property should be same.

Kendo UI with ASP.NET MVC3 default values when adding row to grid

I am converting an existing app from Telerik MVC extensions to the newer KendoUI product. I am using the grid control. How do I specify the default values for the columns when adding a new row to the grid?
With the old Telerik MVC extensions, I did the following:
.Editable(editing=>editing.Mode(GridEditMode.InCell).DefaultDataItem(Model.defaultItem))
The defaultItem of my model was my default for added rows. So how do I do this with Kendo?
Yo yo yo mate,
You need to specify default value for each of the fields via the dataSource model configuration
Here is an example you can use ;)
#(Html.Kendo()
.Grid<TestModel>()
.Name("SomeOtherGridName")
.DataSource(ds => ds.Ajax().Read("test", "test").Model(
x => {
x.Field(c => c.Val1).DefaultValue(5);
x.Field(c => c.Val2).DefaultValue("cool!");
}
))
.Columns(columns =>
{
columns.Bound(c => c.Val1);
columns.Bound(c => c.Val2);
})
)
DefaultDataItem does not currently exist in the MVC extensions specifically. However, it is still possible without using the MVC extensions as a work-around.
I wrote an extension method that accomplishes the core functionality of DefaultDataItem(). It reads every property of a default item and sets the Field() and DefaultValue() in the data source model definition:
public static class DataSourceModelDescriptorFactoryExtensions
{
public static DataSourceModelDescriptorFactory<TModel> DefaultDataItem<TModel>(
this DataSourceModelDescriptorFactory<TModel> dataSourceModelBuilder,
TModel defaultDataItem) where TModel : class
{
var propertyInfos = typeof(TModel).GetProperties();
foreach (var propertyInfo in propertyInfos)
{
dataSourceModelBuilder
.Field(propertyInfo.Name, propertyInfo.PropertyType)
.DefaultValue(propertyInfo.GetValue(defaultDataItem));
}
return dataSourceModelBuilder;
}
}
Use it like this:
#(Html.Kendo().Grid<MyEntity>()
...
.DataSource(ds => ds
...
.Model(model =>
{
model.Id(n => n.Id);
model.DefaultDataItem(myDefaultEntity);
}
)
)

Telerik MVC Grid in Razor view, GridCommand not populating

I have a telerik mvc grid in a Razor view. I am using custom server binding. My issue is that on paging and sorting the GridCommand object properties "Page", "PageSize" & "SortDescriptors" are not getting the correct value. The funny thing is that the exact same code works for an aspx view. Since this is a new view, I have started using "Razor".
My view is -
#(Html.Telerik().Grid((IEnumerable<Mitek.MobileImaging.AdminSite.Models.ImagingTransactionModel>)ViewData["DeficientGridView"])
.Name("DeficientImagesGrid")
.DataBinding(databinding => databinding.Server()
.Select("ViewDeficientImages", "SuperAdmin", new { orgId = ViewData["OrgId"], beginDate = ViewData["BeginDate"], endDate = ViewData["EndDate"], searchString = ViewData["SearchString"] }))
.DataKeys(keys => keys.Add(o => o.TranId))
.EnableCustomBinding(true)
.BindTo((IEnumerable<Mitek.MobileImaging.AdminSite.Models.ImagingTransactionModel>)ViewData["DeficientGridView"])
.Columns(
columns =>
{
columns.Template(
#<text>
<a href="#Url.Action("DeficientImageDetails", "SuperAdmin", new { id = item.TranId }) ">
<img alt="Deficient Image Details" src= "#Url.Content("~/Content/ImagesUI/detail_icon.gif")" style="border:0px" /></a>
</text>
).Title("Actions").Width(75);
columns.Bound(o => o.TranId).Hidden(true);
columns.Bound(o => o.user_email).Title("User Email").Width(250);
columns.Bound(o => o.xml_config_name).Title("Job File").Width(200);
columns.Bound(o => o.datetime_created).Title("Date Created").Format("{0:MM/dd/yyyy}").Width(200);
columns.Bound(o => o.short_note).Title("Note").Width(200);
columns.Bound(o => o.iqa_code).Title("IQA Code").Width(200);
}).HtmlAttributes(new { style = " font-family:arial; font-size: .9em; " })
.Sortable()
.Pageable(paging => paging.Position(GridPagerPosition.Bottom)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Total((int)ViewData["DeficientImagesCount"])
.PageSize(25))
)
The controller looks like
[GridAction(GridName = "DeficientGridView")]
public ActionResult ViewDeficientImages(DeficientImagesViewModel model, GridCommand command, string button)
{
//Some Code......;
GridCommand myCommand = new GridCommand() { PageSize = 25 };
}
The command object never has any values for command.Page, command.SortDescriptors at the time of paging or sorting. Please note that the exact same code works in a asps page.
Please help.
Thanks,
SDD
Can you check if it has to do with [GridAction(GridName = "DeficientGridView"] attribute and your grid name being different.Name("DeficientImagesGrid") ?
You have to change [GridAction(EnableCustomBinding = true, GridName = "DeficientImagesGrid")] to this. I have the same problem today and i found this is working. If you don't specify the GridName then you will not get GridCommand.
gridCommand is NOT populated when the query string parameters are QueueGrid-size=2&QueueGrid-page=3
gridCommand is populated when the query string parameters are size=2&page=3

Categories

Resources