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
Related
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");
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.
By default it looks like Telerik Grid for MVC3 submits only the rows marked as "dirty" to my controller. I need to be able to submit all rows on a Telerik Grid to my controller. In other words I think I need to mark all rows as changed so the grid will send all rows to my controller.
I am using Ajax data binding as in:
.DataBinding(dataBinding => dataBinding
.Ajax()
.Select("GetData", "ModuleAccess", new { roleId = #ViewBag.RoleId, appId = #ViewBag.AppId })
.Update("SaveBatchEditing", "ModuleAccess")
#(Html.Telerik().Grid<BarcodeListModel>()
.Name("orders-grid")
.ClientEvents(events => events.OnDataBinding("onDataBinding"))
.DataKeys(keys =>
{
keys.Add(x => x.Id);
})
.ToolBar(commands =>
{
commands.SubmitChanges();
})
.DataBinding(dataBinding =>
dataBinding.Ajax()
.Select("BulkEditSelect", "ProductVariant")
.Update("BulkEditSaveBarcode", "ProductVariant")
.Delete("DeleteBarcode", "ProductVariant")
)
.Columns(columns =>
{
columns.Bound(x => x.Id).ReadOnly();
columns.Bound(x => x.SKU);
columns.Bound(x => x.barcode);
//columns.Bound(x => x.Id)
// .Template(x => Html.ActionLink(T("Admin.Common.View").Text, "DeleteBarcode", new { id = x.Id }))
// .ClientTemplate("" + "Delete" + "")
// .Width(50)
// .Centered()
// .HeaderTemplate("DeleteBarcode")
// .Filterable(false)
// .Title("Delete");
columns.Command(commands => commands.Delete()).Width(180);
})
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.DataBinding(dataBinding => dataBinding.Ajax().Select("BarcodeList", "ProductVariant", Model))
.Editable(editing => editing.Mode(GridEditMode.InCell))
.EnableCustomBinding(true)
)
use like this code
I found the answer:
function ModuleAccessGridHasChanges() {
var grid = $("#ModuleAccessGrid").data("tGrid");
if (grid != null) {
var additionalValues = grid.data;
if (!$.telerik.trigger(grid.element, 'submitChanges', { values: additionalValues })) {
grid.sendValues($.extend({}, additionalValues), 'updateUrl', 'submitChanges');
}
}
}
Fiddler shows all the data for the grid coming accross:
I am having an issue where the READ operation for the Kendo Grid does not get invoked and hence the grid does not populate any data. I have followed these links
http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/troubleshooting#the-ajax-bound-grid-does-not-populate
Kendo UI Grid is not calling READ method
However the issue still exists.
/// CS File
public ActionResult GetItemsHome([DataSourceRequest] DataSourceRequest request , int page)
{
List<CustomItem> lst = new List<CustomItem>();
return Json(lst.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
///cs html file
#(Html.Kendo().Grid<CustomItem>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(o => o.No).Width("15%");
columns.Bound(o => o.ShortDesc).Width("15%");
columns.Bound(o => o.Category).Width("6%");
})
.Sortable()
.Pageable(p=>p.Refresh(true))
.Filterable()
.Scrollable()
.Editable(edit => edit.DisplayDeleteConfirmation("Are You Sure To Delete This ").Mode(GridEditMode.PopUp))
.ColumnMenu(col=>col.Sortable(false))
.Groupable()
.ToolBar(toolbar => toolbar.Create())
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
//.ClientDetailTemplateId("template")
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(6)
.Read(read => read.Action("GetItemsHome", "det"))
.Model(model => {
model.Id(p => p.ID);
})
.Create(update => update.Action("EditingInline_Create", "det"))
// .Read(read => read.Action("EditingInline_Read", "Default1"))
.Update(update => update.Action("EditingInline_Update", "det"))
.Destroy(update => update.Action("EditingInline_Destroy", "det"))
)
)
the order in which the JS is loaded
Any ideas ?
Thanks
Your action GetItemsHome([DataSourceRequest] DataSourceRequest request , int page) requires page (non-null value) to be passed. You have 3 options:
Delete this argument (this makes sense since request contains everything you want)
Supply it like: .Read(read => read.Action("GetItemsHome", "det", new { page = 10}))
Make it nullable like: int? page
EDIT: After following any of above, return some data from controller action (I am creating some arbitrary data, you may return it from DB instead) to fill up your grid. Something like:
public ActionResult GetItemsHome([DataSourceRequest] DataSourceRequest request , int? page)
{
//List<CustomItem> lst = new List<CustomItem>();
// Dummy data
var data = new [] { new CustomItem(){ No = 1, ShortDesc = "xyz", Category = "abc"},
new CustomItem(){ No = 2, ShortDesc = "xyz", Category = "abc"} };
return Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
If your controller and action names are spelled correctly in view, above code should work.
Some possibilities, if your function is not being called:
If your ActionResult Index() function is doing some other operations instead of simply return View() and exiting, it's possible your GetItemsHome() function may not be called - I had this issue once.
Try just naming the function "Read" instead of "GetItemsHome".
Does your controller have any other functions (i.e. Update, Destroy)? I would comment them out, in case there are syntax issues in them that are causing the issue.
"det", I hope, is the name of your controller.
Why pass in the extra page parameter at all? Try it without it, and use a public variable in your model to hold that value.
I try to create a Ajax-support Paging Nested Grid in Telerik MVC Extension. I have rendered the Nested Grid in browse, can expand row Genre to show the related Albums filtered by GenreId, but when i use Ajax for this nested Grid, it don't work in grid paging. I have upload my project and post some code about my View and Controller.
When i don't use ajax, the gird can work properly but it cannot expand correctly when browse is reloaded, how can i maintain the state of row which had expanded?
I'm gratiful for any help.
My Project:
http://share.vnn.vn/dl.php/11718146
My View:
#{
ViewBag.Title = "Home Page";
Layout = #"~\Views\Shared\_Layout.cshtml";
}
#( Html.Telerik().Grid<MvcMusicCodeFirsr.Models.Genre>(#Model)
.Name("personGrid")
.DataKeys(keys => keys.Add(k => k.GenreId))
.DataBinding(d => d.Ajax().Update( "_Update", "Home" )
)
// .Editable(editing => editing.Mode(GridEditMode.PopUp))
.Columns(c =>
{
c.Bound(m => m.Name).Width(150);
c.Bound(m => m.Description).Width(150);
//c.Bound(m => m.Birthdate);
c.Command(commands =>
{
commands.Edit();
}).Width(80);
})
.DetailView(detailView =>
detailView.Template(
#<text>
#(Html.Telerik().Grid<MvcMusicCodeFirsr.Models.Album>(item.Albums)
.Name("Albums_" + item.GenreId)
.DataBinding(d => d.Ajax())
.Columns(columns =>
{
columns.Bound(o => o.Title).Width(101);
columns.Bound(o => o.Price).Width(140);
})
.Pageable()
.Sortable()
.Filterable()
)
</text>
)
.ClientTemplate(
Html.Telerik().Grid<MvcMusicCodeFirsr.Models.Album>()
.Name("Albums_<#=GenreId#>")
.DataBinding(d => d.Ajax())
.Footer(false)
.ClientEvents(events => events.OnDataBinding("detailGrid_dataBinding"))
.ToHtmlString()
))
.Sortable()
.Pageable()
)
)
<script type="text/javascript">
function detailGrid_dataBinding(e) {
var grid = $(this).data("tGrid"),
masterRow = $(this).closest("tr.t-detail-row").prev(),
dataItem = $("#Grid").data("tGrid").dataItem(masterRow);
grid.dataBind(dataItem.Albums);
e.preventDefault();
}
</script>
My Controller:
MusicStoreEntities db = new MusicStoreEntities();
public ActionResult Index()
{
return View(db.Genres.ToList());
}
[GridAction]
public ActionResult _Select()
{
return View(new GridModel ( db.Genres.ToList()));
}
[GridAction]
public ActionResult _Update()
{
return View(new GridModel { Data = db.Genres.ToList() });
}
Here is an example showing ajax pading for the nested grid: http://demos.telerik.com/aspnet-mvc/grid/hierarchyajax