binding a collection/list to a kendo mvc grid column - telerik

I am trying to bind a list of comments to a column, but it doesn't display anything. I am using an inline Client Template to quickly test it, but no luck. I know for sure there are Comments in the model, but it seems to think that the Comments is undefined or null. Below is my code:
#{
var grid = Html.Kendo().Grid(Model)
.Name("grid")
.Columns(columns =>
{
columns.Bound(l => l.Name);
columns.Bound(l => l.Description);
columns.Bound(l => l.Comments).ClientTemplate("# if(Comments) { for(var i=0; i<Comments.length; i++) {# #=Comments[i].Comment# #}}# ").Title("Comments");
})
.HtmlAttributes(new { style = "height: 850px;" })
.Sortable()
.Scrollable(scr => scr.Height(430))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
);
grid.Render();
}

I suggest creating a JavaScript function and calling it in your client template. Also, it will be easier to debug.
function displayComments(data) {
return $.map(data.Comments, function (e) { return e.Comment; }).join(", ");
}
In your Grid:
columns.Bound(l => l.Comments).ClientTemplate("#= displayComments(data) #").Title("Comments");

Related

Setting options of a Kendo Grid that is inside an Editor Template

Inside the editor template of one of my Grids, A, I have another grid, B. I want to set read and update actions of this Grid based on the current Id in the A.
I've tried using Razor code inside the editor template like this:
// details grid: B
.Read("action", "controller", new { #Model.Id })
But Id was always null, probably because Razor is server-side.
So I've tried to set the Grid inside the main page, in the Edit event of the main Grid.
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.options.transport.read.url = "#Url.Action("", "")".concat('/', e.model.Id);
detailGrid.dataSource.options.transport.update.url = "#Url.Action("", "")".concat("/", e.model.Name);
}
This doesn't work neither. The definition of the Grid in the editor template will overwrite these properties.
This is the main Grid:
#(Html.Kendo().Grid<A>()
.Name("A")
.Columns(columns =>
{
columns.Bound(x => x.Id).Hidden();
columns.Bound(x => x.Name).HtmlAttributes(new { #style = "text-align: left" });
....
columns.Command(command =>
{
command.Edit(); command.Destroy();
});
})
.....
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.Model(model =>
{
model.Id(x => x.Name);
})
.Read("", "")
.Update("", "")
.Destroy("", "")
.Create("", "")
)
.Events(e => e.Edit("EditHandler").Save("SaveHandler"))
)
Inside the editor template of this class, a.cshtml, I have another Grid that I want its Edit and Read Actions include the Id of the Grid A.
#(Html.Kendo().Grid<B>()
.Name("B")
.Columns(columns =>
{
columns.Bound(.....
})
.....
.Editable(edit => edit.Mode(GridEditMode.InCell))
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.PageSize(5)
.Model(model =>
{
model.Id(x => x.Id);
})
.Read("", "")
.Update("", "")
).ToClientTemplate()
)
UPDATE
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.read({ Id: e.model.Id });
detailGrid.dataSource.update({ Name: e.model.Name });
}
As Dion noted, it needs 2 changes:
In the child Grid, B, set the auto bind to false: .AutoBind(false)
Set the ID with read method, not manually as I've been trying.
To overcome this case, I will trigger Grid-B's read manually inside Grid-A's edit event. Follow this setup:
Grid-B Config:
.AutoBind(false)
.DataSource(ds => ds.Ajax()
.Read("action", "controller")
.Update(url => url.Action("update", "controller").Data(paramData)))
Modify Grid-A edit function:
function EditHandler(e) {
var gridB = $("#gridB").getKendoGrid(),
model = e.model;
gridB.dataSource.read({Id: model.Id});
}
// get Id for update
function paramData() {
return { Id : $("#Id").val(); };
}
Hope this help.
Note: Unlike read, update will be triggered after popup shown then Id field will be already have its value. Therefor you can use Url.Action(...).Data() for this case.

kendo ui grid selecting row ID

I can't get the Kendo UI grid to work properly. All I am trying to do is, when it is double clicked, I want it to redirect to action.
<div class="Grid" id="Grid">
#(Html.Kendo().Grid(Model)
.Name("grdWorkFlow")
.Columns(columns =>
{
columns.Bound(p => p.SablonWorkflowID).Visible(false);
columns.Bound(p => p.Name);
columns.Bound(p => p.Description);
columns.Bound(p => p.DateAdded);
columns.Bound(p => p.Active);
}).Events(events => events.Change("grid_selected"))
.Selectable(p => p.Type(GridSelectionType.Row))
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource.Server().Model(model => model.Id(p => p.SablonWorkflowID))
.Create("Yeni", "Workflow")
)
)
<script type="text/javascript">
function grid_selected(e) {
var grid = $('#Grid').data('grdWorkFlow');
alert('1');
var record = grid.dataItem(grid.select());
alert('2');
var WID = record.SablonWorkflowID;
window.location.href = "#Url.Action("Edit","Workflow",new { wID = 'WID' })";
}
$("#grdWorkFlow").on("dblclick", "tr.k-state-selected", function (e) {
// do something
});
This is my code. I don't get to alert('2'). I have tried various versions of this, using all types of different stuff from the net.
What am i doing wrong here?
You should define grid as:
var grid = $('#grdWorkFlow').data('kendoGrid');

Kendo grid and mvc editor templates

I have an mvc editor template (named ExpenseTypeEdit) defined like this:
#model ExpenseType
#(Html.Kendo().DropDownListFor(et => et.ExpenseTypeId)
.OptionLabel("--Please Select--")
.DataTextField("Description")
.DataValueField("ExpenseTypeId")
.DataSource(datasource => datasource
.Read("GetExpenseTypeList", "Lookup", new { area = "" })
)
.HtmlAttributes(new { width = "98%" })
)
I have a kendo grid that looks something like this:
#(Html.Kendo().Grid<ExpenseViewModel>()
.Name("ExpenseGrid")
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Columns(columns =>
{
columns.Bound(e => e.ExpenseType)
.EditorTemplateName("ExpenseTypeEdit");
columns.Command(command =>
{
command.Custom("SaveExpense").Click("SaveExpense_click").Text("Save");
}
);
})
.DataSource(datasource => datasource.Ajax()
.ServerOperation(false)
.Model(model =>
{
model.Id(i => i.ExpenseId);
model.Field(f => f.ExpenseType)
.DefaultValue(new Solutions.Business.Entities.PrimitiveObjects.ExpenseType { ExpenseTypeId = 0, Description = "" });
})
)
)
The function SaveExpense_click looks like this:
function SaveExpense_click(e) {
var item = this.dataItem($(e.currentTarget).closest("tr"));
/*
Variable 'item' looks like like:
{
ExpenseType: {
ExpenseTypeId: 4,
Description: ""
}
}
*/
//debugger;
};
The ExpenseTypeId is present but not the description. Why is item not picking up the Description from the drop down and what do I need to do to get it passed in?
You can't get the Description of a DDL server side, you can only get the value. You can either get the value then retrieve the text from the DB or you can use the combo box control and then you will be able to get both value and text.
Just noticed your tryign to get it client side, if thats the case.
$("#ExpenseTypeId").text() should work, as per your example item.text() might work

I understand how to use template with script but not with server controls

Now what I am trying to do is a hybrid or server controls and javascript. I think kendo server controls are elegant.
As you can see I am desparately trying to find how to access editable property in the grid but have no luck.I thought it would be
var grid = $("#Grid").data("kendoGrid");
grid.editable.template = function () { kendo.template($("#MyTemplate").html()) };
The idea is that when a user click on the edit button they get to see #MyTemplate instead of kendo default html version of it. Perhaps, I need to go in a different direction please guide me.
Here is my full code just for reference.
#model IEnumerable<Msh.Intranet.Models.ApiAdFileDisplayGridModel>
<script type="text/x-kendo-template" id="myTemplate">
<input data-bind="value: Id" name="Id"/>
</script>
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Id).Visible(false);
columns.Bound(p => p.FileName).Visible(false);
columns.Bound(p => p.FormNumber);
columns.Bound(p => p.FormTitle);
columns.Bound(p => p.Class);
columns.Bound(p => p.SecondaryCategory).Title("Category") ;
columns.Bound(p => p.RevisionDate).Format("{0:MM/dd/yyyy}");
columns.Command(c =>
{
c.Edit();
c.Destroy();
});
})
.Selectable()
.Groupable()
.Pageable()
.Filterable()
//.Sortable()
.ToolBar(tools =>
{
tools.Create();
})
.Editable(editor => editor.Mode(GridEditMode.PopUp))
.DataSource(dataSource => dataSource
.Ajax()
//this tells kendo I am the primary key
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.RevisionDate);
})
.Read(read => read.Url(#Url.Action("ApiAdFileDisplayGrid","api",null,null)).Type(HttpVerbs.Get))
.Create(create=>create.Url(#Url.Action("ApiAdFileDisplayGrid","api",null,null)).Type(HttpVerbs.Post))
.Update(update=>update.Url(#Url.Action("ApiAdFileDisplayGrid","api",null,null)).Type(HttpVerbs.Put))
.Destroy(destroy=>destroy.Url(#Url.Action("ApiAdFileDisplayGrid","api",null,null)).Type(HttpVerbs.Delete))
)
)
<script type="text/javascript">
$(function () {
var grid = $("#Grid").data("kendoGrid");
//grid.bind("change", function () {
// alert("Change ");
//});
grid.bind("dataBound", function (data) {
alert("dataBound");
});
grid.bind("edit", function (e) {
if (e.model.isNew()) {
//create
alert("new");
} else {
//edit
alert("edit");
}
})
// WebAPI needs the ID of the entity to be part of the URL e.g. PUT /api/Product/80
grid.dataSource.transport.options.update.url = function (data) {
var baseUrl = "#Url.Content("~/api/ApiAdFileDisplayGrid/")" +data.Id;
return baseUrl;
}
// WebAPI needs the ID of the entity to be part of the URL e.g. DELETE /api/Product/80
grid.dataSource.transport.options.destroy.url = function(data) {
var baseUrl = "#Url.Content("~/api/ApiAdFileDisplayGrid/")" + data.Id;
return baseUrl;
}
grid.editable.template = function () { kendo.template($("#MyTemplate").html()) };
});
</script>
To customize the editor you should use the MVC Editor templates engine. Follow the approach in this code library.
I found this thread in kendo site which give me an alternative to my method of doing templates:
http://www.kendoui.com/forums/mvc/grid/new-client-details-template.aspx#2427170
However, it would be interesting to see how to interact with the javascript objects the kendo html helpers create.

Telerik.Web.Mvc grid. In the .DetailView not calling the Ajax method

I am using free Telerik.Web.Mvc grid and following this example: http://demos.telerik.com/aspnet-mvc/grid/hierarchyajax
My Issue:
I am populating the grid with search results after user input some data and submit with a search button
In the DetailView() method I reference my 'SearchQuote_QuotesForHierarchyAjax' method, which is in defined in my Controller when DetailView executes data should be fetched, but this controller action does not execute for me.
If i load the grid first time page loads it execute. but not when the grid is loaded in a search button click
The Code in my project:
My SearchQuote.aspx View looks like this
<%= Html.Telerik().Grid(Model.QuoteSummaryList)
.Name("SearchQuoteGrid")
.Columns(columns =>
{
columns.Bound(q => q.QuoteId).Title("Quote #").Width(50);
columns.Bound(q => q.AxiomId).Title("Axiom Id").Width(180);
})
.ClientEvents(events => events.OnRowDataBound("quotes_onRowDataBound"))
.DetailView(details => details.ClientTemplate(
Html.Telerik().Grid(Model.QuoteSubSummaryList)
.Name("Quotes_<#= QuoteId #>")
.Columns(columns =>
{
columns.Bound(o => o.PositionCode).Width(101);
columns.Bound(o => o.Group).Width(140);
})
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("SearchQuote_QuotesForHierarchyAjax", "SearchQuote", new
{quoteid ="<#= QuoteId #>"}))
.Pageable()
.Sortable()
.Filterable()
.ToHtmlString()
))
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("SearchQuote_Select", "SearchQuote"))
.Sortable()
.Pageable(p => p.PageSize(3))
%>
<script type="text/javascript">
function expandFirstRow(grid, row) {
if (grid.$rows().index(row) == 0) {
grid.expandRow(row);
}
}
function quotes_onRowDataBound(e) {
var grid = $(this).data('tGrid');
expandFirstRow(grid, e.row);
}
</script>
And SearchQuoteController has this code.
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult SearchQuote_QuotesForHierarchyAjax(int quoteid)
{
List<QuoteLineSummaryDM> sublist = new List<QuoteLineSummaryDM>();
QuoteLineSummaryDM a = new QuoteLineSummaryDM();
a.PositionCode = "50";
a.Group = "1";
sublist.Add(a);
QuoteLineSummaryDM b = new QuoteLineSummaryDM();
b.PositionCode = "40";
b.Group = "2";
sublist.Add(b);
var qrows = (from r in sublist
select r).AsQueryable();
return View(new GridModel(qrows));
}
What am I missing? My version is even simpler than the demo. Any ideas?
Thanks.
I found another grid that does what I want to do. It's called jqGrid

Resources