For some time I read the forum to address various issues concerning multiple nestings Grid / TabStip with Ajax Binding.
On the forum many posts relate to these problems.
In my current project I wanted to use a Grid with a detailview containing a tabstrip (LoadOnDemand), which contains Ajaxed Grid or Ajaxed(LoadOnDemand) TabStrips (With Ajaxed.... and so on).
Following investigations into the code of the package, I corrected with some changes that solved my problems.
It seems that now I can embed/nest Ajaxed components(Grid/TabStrip) infinitely (deeply).
I work with
.net 4.0
MVC 3.0
Telerik MVC 2010.3.1318
(Automapper, Ninject...)
in Grid.cs :
private GridBindingSettings Server //Line 218. instead of public
public GridBindingSettings CurrrentBinding //Line 762. instead of private
then replace
Grid.Server.Select with Grid.CurrrentBinding.Select everywhere needed to satisfy the compiler.
in GridUrlBuilder.cs (add test in bold):
if (result.Count == 0) // Line 57. because it is needed only when no binding is provided { foreach (string key in grid.ViewContext.HttpContext.Request.QueryString) { if (key != null && !result.ContainsKey(key)) { result[key] = grid.ViewContext.HttpContext.Request.QueryString[key]; } } }in telerik.tabstrip.js (don't only use ContentUrl, but items href if not an alias. add the bold lines):
(function ($) { var $t = $.telerik; $t.tabstrip = function (element, options) { this.element = element; var $element = $(element); this.$contentElements = $element.find('> .t-content'); $.extend(this, options); if (this.contentUrls) $element.find('.t-tabstrip-items > .t-item') .each($.proxy(function (index, item) { var $link = $(item).find('.t-link'), href = $link.attr('href'); var isAnchor = (href && (href.charAt(href.length - 1) == '#' || href.indexOf('#' + this.element.id + '-') != -1)); if (isAnchor) $(item).find('.t-link').data('ContentUrl', this.contentUrls[index]) else $(item).find('.t-link').data('ContentUrl', href) }, this));Didn't see any errors at this time... :)
Is that correct ?
14 Answers, 1 is accepted
I use T4 template for Mvc for Action Names and Controller Names.
index.aspx (Ajaxed Grid with LoadOnDemand TabStrip):
<%: Html.Telerik().Grid<RBid_DTO>() .Name("Bids") .DataKeys(keys => { keys.Add(x => x.Bid_Number); }) .Columns(columns => { columns.Bound(x => x.Bid_Number); columns.Bound(x => x.Buyer_Id); columns.Bound(x => x.Bid_Status); columns.Bound(x => x.Date_Delevery_Due); columns.Bound(x => x.Date_Entered); }) .DetailView(details => details.ClientTemplate( Html.Telerik().TabStrip() .Name("TabStrip_<#= Bid_Number #>") .SelectedIndex(0) .Items(parent => { parent.Add() .Text("Items") .LoadContentFrom( MVC.Bid.ActionNames._getBidView, MVC.Bid.Name, new { Bid_Number = "<#= Bid_Number #>", Bid_View = Url.Encode(MVC.Bid.Views._BidLines) }).ToString(); parent.Add() .Text("Vendors Information") .LoadContentFrom( MVC.Bid.ActionNames._getBidView, MVC.Bid.Name, new { Bid_Number = "<#= Bid_Number #>", Bid_View = Url.Encode(MVC.Bid.Views._BidVendors) }).ToString(); }) .ToString() ) ) Action to get the views:
[HttpGet] // Ajax GET by TabStrippublic virtual ActionResult _getBidView(string Bid_Number, string Bid_View){ var model = new RBid_DTO {Bid_Number = Convert.ToInt32(Bid_Number)}; return PartialView(Bid_View, model);}_BidVendors.ascx (ajaxed Grid):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<RBid_DTO>" %><% Html.Telerik().Grid<RBidVendor_DTO>() .Name("Grid_BidVendors_" + Model.Bid_Number.ToString()) .DataBinding(dataBinding => dataBinding.Ajax() .Select( MVC.Bid.ActionNames._getBidVendors, MVC.Bid.Name, new { Bid_Number = Model.Bid_Number.ToString() }) ) .Columns(columns => { columns.Bound(c => c.Vendor_Id); columns.Bound(c => c.Vendor_Name); columns.Bound(c => c.Address_City); columns.Bound(c => c.Address_PostalCode); columns.Bound(c => c.Address_Country); columns.Bound(c => c.Bid_Email); }) .Filterable() .Sortable() .Render();%>_BidLines.ascx (ajaxed Grid)
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<RBid_DTO>" %><% Html.Telerik().Grid<RBidLine_DTO>() .Name("Grid_BidLines_" + Model.Bid_Number.ToString()) .DataBinding(dataBinding => dataBinding.Ajax() .Select( MVC.Bid.ActionNames._getBidLines, MVC.Bid.Name, new { Bid_Number = Model.Bid_Number.ToString() }) ) .Columns(columns => { columns.Bound(c => c.Bid_LineNumber); columns.Bound(c => c.Item_Description); columns.Bound(c => c.Purchase_Qty); }) .Filterable() .Sortable() .Render();%>Please review this code fix for all binding (server, service, ajax) problem when multiple components are embedded !
Thanks for your work.
This fix cover :
When Grids are builded, the routes of the Request are first used (the one from a Ajax call to PartialViewResult, described in the TabStrip LoadContentFrom for example...).
The binding of the nested Grids (Ajax, Service or Server) will then be sadly ignored....
Somebody will have a look at this !?
I read the entire forum thread and I cannot understand what the problem which you are trying to fix is. I think you are most probably not including the required JavaScript files for the grid - a problem which has been documented here. You can also check this code library showing how to use a grid inside a tabstrip when the grid is loaded via ajax.
Regards,
Atanas Korchev
the Telerik team
Based on the GridLoadedWithAjaxInTabStrip sample:
Upgraded to 2010.3.1318 still MVC 2.
I modified Index.aspx this way but it doesn't work :
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% Html.Telerik().Grid<GridLoadedWithAjaxInTabStrip.Models.Customer>()
.Name("Grid_Root")
.Columns(columns =>
{
columns.Bound(c => c.ID).Width(200);
columns.Bound(c => c.Name);
})
.DetailView(details => details.ClientTemplate(
Html.Telerik().TabStrip()
.Name("TabStrip_<#= ID #>")
.SelectedIndex(0)
.Items(tabs =>
{
tabs.Add()
.Text("List One")
.LoadContentFrom("Grid", "Home", new { tabstrip = "one", num = "<#= ID #>" });
tabs.Add()
.Text("List two")
.LoadContentFrom("Grid", "Home", new { tabstrip = "two", num = "<#= ID #>" });
}).ToString()
))
.DataBinding(dataBinding => dataBinding.Ajax().Select("_Select", "Home", new { grid = "0" })) /* configure the grid for ajax binding */
.Sortable()
.Pageable()
.Groupable()
.Filterable()
.Render();
%>
<%--
<%: Html.Telerik().TabStrip()
.Name("TabStrip")
.SelectedIndex(0)
.Items(tabs =>
{
tabs.Add().Text("List One").LoadContentFrom("Grid", "Home", new { tabstrip = "one", num = "1" }); // Define the action method which will render the partial view (Grid.ascx)
tabs.Add().Text("List two").LoadContentFrom("Grid", "Home", new { tabstrip = "two", num = "2" }); // Define the action method which will render the partial view (Grid.ascx)
})
%>
--%>
</asp:Content
With HomeController modified this way :
public ActionResult Grid( string tabstrip, int num)
{
ViewData["num"] = num;
return PartialView();
}
Message = "The parameters dictionary contains a null entry for parameter 'num' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Grid(System.String, Int32)' in 'GridLoadedWithAjaxInTabStrip.Controllers.HomeController'. An optional parameter ...
That's why I proposed to modify telerik.tabstrip.js.
What is the official solution ?
Thank you for your response.
- Frederic
Could you please send us the modified code?
Regards,Atanas Korchev
the Telerik team
TabStrip builder problem... so I take tab item href... (telerik.tabstrip.js. is modified...)
Cannot reproduce my binding problem in the sample...
It appears when bindings is at beginning of the grid builder description.
At this time AjaxBinding is defined but ServerBinding is used everywhere.
While looking in the code I found that CurrentBinding was not used... and it seems to be defined for this...
You can see for example that the link on the refresh button of the grid is wrong (it takes the routes of the Tab).
Thank you for reading.
- Frederic
When the grid is ajax bound the link of the refresh button is actually not used at all. It is required only for server binding. This shouldn't be a problem at all.
I checked the suggested code and we cannot include it in our code base because of this line:
if (result.Count == 0)
{
}
The copying of urls is actually needed because users can have more than one grid in the page. This code is copying all query string parameters. You would also not want to lose any state when your user changes the grid page (any query string argument).
Still I am not sure what the initial problem was - you only mention "various problems". What are those various problems? Can I reproduce them with this project? If yes - how? Again having some problem with the url of the refresh link should not be an issue - it is not used when refreshing the grid in this case. Without reproduction I cannot provide any help.
Atanas Korchev
the Telerik team
You can see :
The Grid refresh button href has the link of the TabStrip...
This have no impact in this sample.
But I ran into serious problems in my site, I cannot reproduce in the sample at this time......... :(
- Frederic
Let me know if you manage to reproduce the problem in a sample project. I cannot help without reproducing it first.
Regards,Atanas Korchev
the Telerik team
Thank you for your response.
...
The .js is actually modified in the sample...
Otherwise it will not work.
I checked the javascript files and I think we have applied a similar fix in our code already. You can try using a newer version.
Regards,Atanas Korchev
the Telerik team
I will upgrade to the latest build.