telerik-grid onRowSelect how to get id? - asp.net-mvc

Hi i am new in asp.net mvc and telerik controls. How can i get o.Id value when i click on row?
<%= Html.Telerik().Grid(Model)
.Name("RolesGrid")
.DataKeys(keys => keys.Add(o => o.Id))
.Selectable()
.Columns(columns =>
{
columns.Bound(o => o.Name);
columns.Bound(o => o.Description);
})
.Pageable()
.ClientEvents(events => events
.OnRowSelect("onRowSelect"))
%>
in js code:
function onRowSelect(e) {
var ordersGrid = $('#RolesGrid').data('tGrid');
var row = e.row;
var dataItem = ordersGrid.dataItem(row);
alert(dataItem);
}
But dataItem is null and there is no id value in generated html file. Thanks and sorry for my bad english

So after all i have the best way to get id is:
bind onRowSelect function to your grid
write next code in onRowSelect
var dataItem = jQuery('#MyGridId').data('tGrid').dataItem(e.row);
alert(dataItem['Id']);
dataItem is a map witch have all properties of grid model so you get all you want
Thats all, thanks

From telerik grid demo.
You have to put the Id in the telerik grid as a hidden column.
// ...
.DataKeys(keys => keys.Add(o => o.Id))
.Selectable()
.Columns(columns =>
{
columns.Bound(o => o.Id).Hidden();
columns.Bound(o => o.Name);
columns.Bound(o => o.Description);
})
// ...
.ClientEvents(events => events.OnRowSelect("onRowSelect"))
It will render a
<td style="display: none; ...">...</td>
And then you get it like this:
function onRowSelect(e) {
var id = e.row.cells[0].innerHTML;
// ...
}
Notes:
I know, it's ugly.
I don't know why the telerik forces you to call the .DataKeys(...) method if there's no documented way to get the value for the key defined.
If you use grouping or some other feature it gets trickier, as the hidden column position varies depending on the grouping arrangement.

I found a slightly more elegant way to do this that borrows off of mmutilva's answer.
Start by putting in the hidden column and the change event in the same way:
.DataKeys(keys => keys.Add(o => o.Id))
.Selectable()
.Columns(columns =>
{
columns.Bound(o => o.Id).Hidden();
columns.Bound(o => o.Name);
columns.Bound(o => o.Description);
})
.ClientEvents(events => events.OnRowSelect("onRowSelect"))
But then in the javascript function, there is a better way to actually select the object and then the hidden row:
function onRowSelect(e) {
var grid = e.sender;
var currentitem = grid.dataItem(this.select());
var Id = currentitem.Id;
//then do whatever with the ID variable
}
Source

Change the function onRowSelect to this:
function onRowSelect(sender, args){...}
The sender will be the grid, and from the args you can determine which item was selected.
Look to the Telerik help site for detailed info on how to get the data using the Client Side API:
http://www.telerik.com/help

Related

Telerik Kendo Grid Doesn't Display Value Properly

i'm new to kendo UI and currently learning about custom editor.
My Problem is i managed to get my editor template working in edit mode and populate the data just fine, but somehow it won't save the value to the display grid
I Retreive all my data from API.
UPDATE:
i've managed to properly save the value from the custom editor template to the controller and it works just fine, but using clientTemplate won't display the correct value from what i select in the dropdown, and only show a string
DropDown Only Display A String
my setup code is like this
#( Html.Kendo().Grid<SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Product).ClientTemplate("\\#=Product.ProductId\\#").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Batch(true)
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product);
})
.Create(act => act.Action("DetailCell_Create","SalesOrder"))
)
)
DDLProduct.cshtml:
#model AAF.WEB.MVC.ViewModels.ProductVM
#(
Html.Kendo().DropDownListFor(m => m)
.DataValueField("ProductId")
.DataTextField("ProductName")
.OptionLabel("Select Product")
.BindTo((System.Collections.IEnumerable)ViewData["products"])
)
Edit Mode
DisplayMode / Out of Product Edit Mode
Use template method to acheive dropdown with kendo grid.
GridForeignKey.cshtml - it should placed in shared folder or EditorTemplates
#model object
#(
Html.Kendo().DropDownListFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
In your kendo grid please change like below
#( Html.Kendo().Grid<AAF.WEB.MVC.ViewModels.SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Id)
columns.ForeignKey(c => c.ProductId, (System.Collections.IEnumerable)ViewData["Products"], "ProductId", "ProductName").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
)
You can set the products data to view data. using this method you can save the product id.
Thanks
Okay after i frustrated for many hours, finally found the solution
the solution is to add a defaultvalue to the passed model in the grid
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product).DefaultValue(
ViewData["defaultProduct"] as ProductVM
);
})
and pass the data from the controller
// Function that get data from API
ViewData["products"] = products;
ViewData["defaultProduct"] = products.First();

Kendo UI Grid pass value to edit popup

I'm using Kendo UI MVC and I have a view that contains details about an object. On that page I have a Kendo UI Grid that shows a list of notes about the object. I allow the user to create or edit the notes from the grid.
The problem I have is when the user clicks the add button I need to pass the id of the page's object. I'm using GridEditMode.PopUp.
Basically, this is what I have:
public class Item {
public int Id { get;set; }
...
}
public class Note {
public int ItemId {get;set;}
...
}
Here is the grid code:
#(Html.Kendo()
.Grid<NoteViewModel>()
.Name("kendo-grid")
.Columns(columns =>
{
columns.Bound(n => n.NoteDateTime).Title("Date").Format("{0:MM/dd/yyyy}");
columns.Bound(n => n.NoteDateTime).Title("Time").Format("{0:h:mm tt}").Sortable(false);
columns.Bound(n => n.NoteActivityType).Title("Activity Type");
columns.Bound(n => n.NoteDescription).Title("Description");
columns.Bound(n => n.NoteDetail).Title("Notes");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(200);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Note"))
.Mobile()
.Pageable()
.Sortable()
.Filterable()
.Reorderable(r => r.Columns(true))
.Resizable(r => r.Columns(true))
.DataSource(dataSource => dataSource.Ajax()
.Model(model => model.Id(note => note.Id))
.PageSize(25)
.Sort(sort =>
{
sort.Add(note => note.NoteDateTime);
})
.Read(read => read.Action("ReadNotes", "Case").Data("getCaseId"))
.Create(a => a.Action("CreateNote", "Case"))
.Update(u => u.Action("UpdateNote", "Case"))
.Destroy(d => d.Action("DeleteNote", "Case"))
)
)
I need to set Note.ItemId when the user clicks the add button on the grid. Or, is there a better way to do this, as in send the ItemId value on the post?
I ended up getting this to work by hooking into the edit event of the popup. I wasn't able to figure out how to do it on the initial setup, so I added this to doc ready handler to the edit popup. This kind of feels like a hack, so if someone has a better way I'd love to hear about it. The #ItemId input is already on the details page, so I figured I may as well use it.
$(function () {
function setItemId(event) {
var uid = $('.k-edit-form-container').closest('[data-role=window]').data('uid');
var model = $('#kendo-grid').data('kendoGrid').dataSource.getByUid(uid);
if (model.get('ItemId') === 0) {
model.set('ItemId', Number($('#ItemId').val()));
}
}
var grid = $('#kendo-grid').data('kendoGrid');
grid.bind('edit', setItemId);
});
I'm not sure if it's possible what you want, but to get you on the way this is how you'd start doing it.
You generally want a flat viewmodel, containing everything you want to use.
public class NoteViewModel {
public int ItemId { get;set; }
}
Then properly setup the use of your editor template. Since your ItemId is now part of the grid's model it'll be send to the controller on edit/create.
#(Html.Kendo()
.Grid<NoteViewModel>()
.Name("kendo-grid")
.Columns(columns =>
{
columns.Bound(n => n.ItemId).Hidden();
columns.Bound(n => n.NoteDateTime).Title("Date").Format("{0:MM/dd/yyyy}");
columns.Bound(n => n.NoteDateTime).Title("Time").Format("{0:h:mm tt}").Sortable(false);
columns.Bound(n => n.NoteActivityType).Title("Activity Type");
columns.Bound(n => n.NoteDescription).Title("Description");
columns.Bound(n => n.NoteDetail).Title("Notes");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(200);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("NoteTemplate"))
Etc...
)
Finally create your template (called NoteTemplate.cshtml) and place it in Views/Shared/EditorTemplates so Kendo can find it.
#model NoteViewModel
Date: #Html.EditorFor(l => l.NoteDateTime)
Note Description: #Html.EditorFor(l => l.NoteDescription)
(Add all fields you need to edit here)
I had same problem
Problem is that some of fields of the model(viewmodel) is nullable
Model nullable field is not fully supported in Kendo UI

Multiselect list in Kendo Grid inline editing

I need to use multiselect list in kendo grid (inline editing) so that user can select multiple values from the list per row.
Following are my requirements:
At the time of display, kendo grid should show comma separated list of all the selected values.
At the time of Add, kendo grid should show multiselect list and allow to select multiple values.
At the time of Edit, kendo grid should show multiselect list with already selected values. User should be able to modify the select and add/remove items from the list.
When user clicks on update/save button, selected values from multiselect list should be available in code behind (in update ajax action) along with id of row.
Following what I do as of now:
I am taking an approach similar to using a drop down list in kendo inline grid.
I have created an Editor Template for displaying multiselect at the time of add/edit.
Following is the code:
#model List<Namespace.CompanyConnector>
#using Kendo.Mvc.UI
#(Html.Kendo().MultiSelectFor(c=>c)
.Name("company_connector_id")
.DataTextField("connector_name")
.DataValueField("company_connector_id")
.Placeholder("Select connector...")
.AutoBind(false)
.Value((List<int>)ViewData["SelectedValues"])
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCompanyConnectors", "BrandConnector");
})
.ServerFiltering(true);
})
)
#Html.ValidationMessageFor(m => m)
Explanation: I bind a list of model class to the multiselect and set data source in the read action. For selecting the selected values at the time of edit, I have created a function that returns the ids of selected values and put that in View Data in the read action.
I've used this Editor template in my Index page as following code:
#{Html.Kendo().Grid<Cee.DomainObjects.DomainObjects.BrandConnector>()
.Name("BrandConnectorGrid")
.Filterable()
.Events(e => e.Edit("onEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Events(e => e.Error("error_handler").RequestEnd("onRequestEnd"))
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.brand_id);
model.Field(e => e.CompanyConnectorList).DefaultValue(new
List<Cee.DomainObjects.DomainObjects.CompanyConnector>());
})
.Read(read => read.Action("_AjaxBinding", "BrandConnector",new{companyID = 0 }).Type(HttpVerbs.Post))
.Update(update => update.Action("_UpdateBinding", "BrandConnector").Type(HttpVerbs.Post)))
.Columns(columns =>
{
columns.Bound(c => c.brand_connector_id).Width(0).Hidden(true);
columns.Bound(c => c.company_id).Width(0).Hidden(true);
columns.Bound(c => c.brand_id).Width(0).Hidden(true);
columns.Bound(u => u.brand_name).Title("Brand").Width("18%").HtmlAttributes(new { #class = "brkWord", #readonly = "readonly" });
columns.ForeignKey(u => u.connector_name, Model.CompanyConnectorList, "company_connector_id", "connector_name").Title("Connector").Width
("16%").HtmlAttributes(new { #class = "brkWord" }).EditorTemplateName("company_connector_id");
columns.Command(p => p.Edit().Text("Edit").HtmlAttributes(new { #title = "Edit" })).Width("16%").Title("Edit");
})
.Editable(editable => editable.Mode(GridEditMode.InLine).CreateAt(GridInsertRowPosition.Top))
.Pageable(pageable => pageable.Refresh(true).PageSizes(GlobalCode.recordPerPageList).ButtonCount(GlobalCode.PageSize).Input(true).Numeric(true))
.HtmlAttributes(new { #class = "dynamicWidth" })
.Sortable(sorting => sorting.Enabled(true))
.Render();
}
Explanation: I've used ForeignKey. Bound it to the string column "connector_name". Connector_name is a comma separated list of IDs that I send from controller. Editor template is used here.
Issue: It works fine at the time of View/Display in Index but Edit does not show selected value. Also we do not get updated value in code behind on update click.
Is this correct way of implementing multiselect list or do I need to bind a collection property as a column in grid?
If I bind a collection property as a column then how would I be able to show comma separated string at the time of display?
Try below code:
function onEdit(e) {
var multiselect = $("#YourMutliselectDropdown").data("kendoMultiSelect");
var IDArray = [];
$(e.model.propertyName).each(function (index) {
var ID = e.model.propertyName[index].id;
IDArray.push(ID);
});
multiselect.value(IDArray);
}
I assume that propertyName is List of your collection and it contains id as property.
try it:
c.Bound(p => p.CompanyConnectorList).ClientTemplate("#= connectorsToString(data)#").EditorTemplateName("company_connector_id");
and js:
function connectorsToString(data) {
var list = data.company_connector_id;
var result = "";
for (var i = 0; i < list.length; i++) {
result += list[i].Name + ';';
}
return result;
}

Disabling some rows in Telerik ASP.NET MVC grid based on a model's field

I have a Telerik asp.net grid on my view. The model that is connected to this grid has a field named "State". This field holds the state of each row. Based on this state, user can edit some of the rows, and can't edit the rest. For example if state of a row is 0, the user can edit it, otherwise the edit button and other commands of that row must be disabled.
So my question is: Is there a way to disable some of the rows based on the model's fields?
here is the simplified grid:
#{Html.Telerik().Grid<StationEvaluation>().Name("ManagementGrid").DataKeys(dataKeys => dataKeys.Add(o => o.StationEvaluationID)).Groupable().Filterable().Pageable().Sortable().DataBinding(dataBinding => dataBinding.Ajax()
.Delete("DeleteFromGrid", "StationEvaluation")
).Columns(columns =>
{
columns.Command(commands =>
{
commands.Delete().ButtonType(GridButtonType.Image);
commands.Custom("Edit").Action("Edit", "StationEvaluation").ButtonType(GridButtonType.Image).Text("Edit");
}).Title("Manage").Width(50);
columns.Bound(o => o.FromDate);
columns.Bound(o => o.ToDate);
columns.Bound(o => o.DateShow);
columns.Bound(o => o.State).ClientTemplate("<#= StateDsc #>");
columns.Command(commands =>
{
commands.Custom("NextState").Action("NextState", "StationEvaluation").ButtonType(GridButtonType.Text).Text("Next state").Ajax(true);
commands.Custom("PreviousState").Action("PreviousState", "StationEvaluation").ButtonType(GridButtonType.Text).Text("Previous state").Ajax(true);
}).Title("Change state").Width(50);
}).Render();
}
I found the solution. The onRowDataBound event must be added to the gird. In this method I can hide the columns that user needs them to edit:
function ManagementGrid_onRowDataBound(e) {
var dataItem = e.dataItem;
if (dataItem.State == 0)
{
$(e.row).find("a.t-grid-PreviousState").hide();
}
else if (dataItem.State == 4) {
$(e.row).find("a.t-grid-NextState").hide();
}
}

Telerik Grid MVC Razor : auto select a row and fire select event

Using a Telerik Grid with ASP.NET MVC 3 Razor engine.
When a user selects a row, we un-hide some part of the page. This is working fine when I click on a row.
However, I need to automatically select the first row when the page is loaded
I can change the row display color so it appears selected, but I can't figure out how to have the select event called!
Here is the grid code :
#(Html.Telerik().Grid<SomethingViewModel>()
.Name("SomethingGroupGrid")
.ClientEvents(events =>
{
events.OnDataBinding("SomethingGroupGrid_onDataBinding");
})
.DataBinding(dataBingding => dataBingding.Ajax().Select("SomethingGroupGrid", "Something"))
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden();
columns.Bound(c => c.Name)
.Title("Groups");
})
.Selectable()
.Pageable(x => x.PageSize(10))
.ClientEvents(events => events.OnRowSelect("SomethingGroupGrid_RowSelect"))
)
Can someone help?
Ok I found a freakishly ugly solution :
I added a OnRowDataBound event on the grid. This OnRowDatabound Functions fires the OnRowSelect events.
Then I added page global javascript variable to hold a bool value that checks if the first row has been selected, so the OnRowDatabound does not call OnRowSelect for each row.
#(Html.Telerik().Grid<SomethingViewModel>()
.Name("SomethingGroupGrid")
.ClientEvents(events =>
{
events.OnDataBinding("SomethingGroupGrid_onDataBinding");
})
.DataBinding(dataBingding => dataBingding.Ajax().Select("SomethingGroupGrid", "Something"))
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden();
columns.Bound(c => c.Name)
.Title("Groups");
})
.Selectable()
.Pageable(x => x.PageSize(10))
.ClientEvents(events => events.OnRowSelect("SomethingGroupGrid_RowSelect"))
.ClientEvents(events => events.OnRowDataBound("SomethingGroupGrid_OnRowDataBound"))
)
<script type="text/javascript">
var firstRowSelected = false;
function PreviewAccountGrid_DataBound(e) {
if (firstRowSelected == false) {
SomethingGroupGrid_RowSelect(e);
firstRowSelected = true;
}
}
</script>
Plese tell me that there is a better way to do that, or it will severely degrade my opinion of Telerik controls (which is already damn low).

Resources