This is a migrated thread and some comments may be shown as answers.

[Solved] bind to model and load on demand

7 Answers 138 Views
TabStrip
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
A
Top achievements
Rank 1
A asked on 26 Aug 2011, 02:59 PM
Hi,

I'm trying to create a tabstrip by binding to a model. A configuration file will declare how many tabs there wil be. All tabs will direct to the same controller with different values. I want all tabs to load content on demand. In all examples that use the LoadContentFrom method the contents is static. I have found someone with the same question here. But there is no answer.

My solution does load all the content as required but returns a partial view instead of showing the new content in place. Just the partialview is shown. My guess is there is a problem with loading; it isn't loaded asynchronously.

I have browsed the code of Telerik; LoadContrentFrom in the end uses a UrlHelper.Action method.

Here's some code.
BTW I have created an extension method to be able to debug the code that is supposed to go in to the view. Here's (part of) my view:

<div class="tabcontainer">
                        @Html.GetTabstrip(tabservice.Planning)@'Planning contains the items for the menu
                    </div>
                    <div >
                        <h1>Some text</h1>
                    </div>
                    <div class="tabcontainer">
                         @Html.Action("Planning", New With {.day = DateTime.Today})
                    </div>

 


Here 's GetTabstrip method.
<System.Runtime.CompilerServices.Extension()>
Public Function GetTabstrip(helper As HtmlHelper, availableItems As IEnumerable(Of MW.Telerik.Ui.Extensions.IMwForTNavgationItem)) As Telerik.Web.Mvc.UI.TabStripBuilder
Dim bindingDelegate As Action(Of Telerik.Web.Mvc.UI.TabStripItem, IMwForTNavgationItem)
bindingDelegate = AddressOf TelerikExtensionHelper(Of Telerik.Web.Mvc.UI.TabStripItem).SetAction
 
Return helper.Telerik().TabStrip().Name("Tabs").BindTo(Of IMwForTNavgationItem)(availableItems, bindingDelegate)
End Function

Here is the SetAction method:
Public Shared Sub SetAction(telerikNavigationItem As TNavigationItem, mwNavigationItem As IMwForTNavgationItem)
 
        Dim values As System.Web.Routing.RouteValueDictionary
        If (mwNavigationItem.RouteValues Is Nothing) Then
            values = New RouteValueDictionary()
        Else
            values = mwNavigationItem.RouteValues
        End If
        telerikNavigationItem.Action("Planning", "Planning", mwNavigationItem.RouteValues)
        telerikNavigationItem.Text = mwNavigationItem.Text
        telerikNavigationItem.Enabled = mwNavigationItem.Enabled
        telerikNavigationItem.Visible = True
        If (Not String.IsNullOrEmpty(mNavigationItem.ImageUrl)) Then telerikNavigationItem.ImageUrl = mwNavigationItem.ImageUrl
        telerikNavigationItem.Selected = mwNavigationItem.Selected
    End Sub

Here's the Planning method on the controller Planning
Function Planning(day As DateTime) As ActionResult
        Dim planningService As New PlanningService()
        Dim model As New TreeViewModel 'A model to bind to a tree
        model.Items = planningService.GetDayplanning(day)
        'all items in the model implement there respective routevalue
        Return PartialView("../TreeView/_TreeView", model)
    End Function

Browsing the Telerik code I have seen that LoadContent from is called on ContentNavigationItemBuilder and returns a TBuilder. So in my case that would be a Tabstripbuilder. Where should I 'get' it or create it? My guess would be the SetAction method.

Or is my problem something completely different?

BTW As you can see I'm loading a tree view for each tab. So I also experience this problem.








7 Answers, 1 is accepted

Sort by
0
Atanas Korchev
Telerik team
answered on 26 Aug 2011, 04:03 PM
Hello A,

 You can wire the ItemDataBound handler of the tabstrip and set the ContentUrl property of the bound tab:

@(Html.Telerik().TabStrip() _
     .Name("TabStrip") _
     .BindTo(New String() {"One", "Two"} , Sub(tab, data)
        tab.Text = data 'set tab text
        tab.ContentUrl = Url.Action("TabContent", New With { .tab = data }) 'set tab content url
     End Sub)
)

Find attached a complete project.

Kind regards,
Atanas Korchev
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
A
Top achievements
Rank 1
answered on 29 Aug 2011, 11:08 AM
Hi,

I implemented your code. As far as I can see it does the same as my code, the URL's are the same anyway. So maybe the problem is reloading the treeview. This causes an exception and afterwards only the treeview is shown. So I will probably have to solve the loading problem off the tree view first to what happens than.

Microsoft JScript runtime error: The value of the property '$' is null or undefined, not a Function object

I have tried adding loaidng the treeview in the view , but that causes athe following exception:

Microsoft JScript runtime error: 'jQuery' is undefined

Any idea's
0
Atanas Korchev
Telerik team
answered on 30 Aug 2011, 07:09 AM
Hello A,

 Is there a chance to modify the attached project so it fails in the same way as your application?

Regards,
Atanas Korchev
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
A
Top achievements
Rank 1
answered on 31 Aug 2011, 11:34 AM
Hi, I will see what I can do in regards to your question of modifying the attached solution.

For the time being I will give new and more info. BTW since my last post I have add a splitter to my main view.  
By adding several script files I have been able to overcome the script problem. To be able to understand the problem better I have tried to recreate the examples, but the result of clicking the tab still renders a partial view instead of a partial view within a page.

Here is my code: 
@Html.Telerik().Splitter().Name("Splitter1").Panes(Sub(panes)
                                                                       Dim pane1 = panes.Add()
                                                                       pane1.Size("40%")
                                                                       pane1.Content(Html.Action("LeftPanelPlanning", "Planning").ToString)
                                                                       pane1.Resizable(True)
                                                                         
                                                                       Dim pane2 = panes.Add()
                                                                       pane2.Size("40%")
                                                                       pane2.Content(Html.Action("MiddlePanelPlanning", "Planning").ToString)
                                                                       pane2.Resizable(True)
                                                                         
                                                                       Dim pane3 = panes.Add()
                                                                       pane3.Size("20%")
                                                                       pane3.Collapsible(True)
                                                                       pane3.Resizable(True)
                                                                       pane3.Content(Html.Action("RightPanelPlanning", "Planning").ToString)
                                                                   End Sub)

Right now we are talking about the middlePanelPlanning (I mistakenly called it Panel. It should be pane). This renders a good page.

MiddlePanelplanning Action
Function MiddlePanelPlanning() As ActionResult
       Return PartialView()
   End Function

The corresponding view is as follows:
<div class="tabcontainer">
    @Html.Telerik().TabStrip().Name("TabStrip").Items(Sub(parent)
                                                          Dim child = parent.Add()
                                                          child.Text("Planning vandaag")
                @*/* this tab will be opened initially - no need to get it with ajax */*@
                                                          child.Content(Html.Action("Planning", "Planning", New With {.day = DateTime.Today}).ToString)
                                                          child.Selected(True)
                                                             
                                                          Dim child2 = parent.Add()
                                                          child2.Text("Planning morgen")
                                                          child2.Action("Planning", "Planning", New With {.day = DateTime.Now.AddDays(1)})
                  
                                                          Dim child3 = parent.Add()
                                                          child3.Text("Planning overmorgen")
                                                          child3.LoadContentFrom("Planning", "Planning", New With {.day = DateTime.Now.AddDays(2)})
                                                             
                                                      End Sub)
    </div>

The view loaded from the action Planning is the same as I said in the original post. The treeview loaded is as follows:

<script type="text/javascript">
 var ScriptManager = null; 
  
    $(document).ready(function (){
        ScriptManager = GridScriptManager('Planning', 'Action', 'Model.Name');     
    });
      
        function OnRowSelect(e){ 
          
        }
</script>
<div id='divDrop@(Model.TreeViewName)' class='DropContainer'>
@Html.GetTree(Model)
</div>


  The gettree method is an extension method to better debug code. Like I said, when loading a page the first time everything is fine, but when clicking the second tab the result is a partial view with a tree instead of a whole page. 


0
A
Top achievements
Rank 1
answered on 01 Sep 2011, 08:46 AM
Hi,

    I have been able to solve part of the problem. It turned out to be a javascript loading problem. My partialviews didn't load tabstrip, it loaded menu instead :( . If I use Telerikcode directly in my view every tbhing works as it should be. If use my extension code it doesn't. So it's my code that doesn't work as expected. Which leads to my original question. I'm working on that.
0
A
Top achievements
Rank 1
answered on 05 Sep 2011, 10:45 AM
Just to let everybody know binding to a model and load on demand is possible. How did I do it?

Some remarks first:
      1. My solution uses an extension method. I have said before I use that to be able to better debug my code. In a view the standard code from Telerik is executed as one statement. With long statements composed of several sub statements it is virtually impossible to know what is wrong when you get a message like nullreference exeption. Furthermore, I use VB.Net. All examples are in C# and lambda expressions in C# are readable and understandable, but in VB there is just to much text to my liking. Anyway, I think my solution will also work without the extension method, but I haven't tested it. Feel free.
2. Secondly, the solution is not my preferred coding standard, but for now it works so I will try to fix it later. 
   
To get to it:
Here's my view: 
@Html.GetTabstripWithAsynchronousContent(tabservice.Content(Url))

The tabservice returns a list of a custom Interface that resembles the interface of telerik (for this solution to work this is not strictly necessary. One could use the Telerik classes and/or interface, but I prefer to program to my own interface for loose coupling). The method 'Content(Url)' uses the 'urlHelper.Action' to set the contentUrl property. The parameter 'Url' is of type 'UrLHelper'. 

(This is where I need to do some refactoring. This service is depend on the URLhelper from the view, which is context depend. That complicates writing unit tests).

Furthermore I have created an extension method:
''' <summary>
    ''' Gets a TabStrip
    ''' </summary>
    ''' <param name="helper"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Runtime.CompilerServices.Extension()>
    Public Function GetTabstripWithAsynchronousContent(helper As HtmlHelper, availableItems As IEnumerable(Of IMwForTNavgationItem)) As Telerik.Web.Mvc.UI.TabStripBuilder
        Dim bindingDelegate As Action(Of Telerik.Web.Mvc.UI.TabStripItem, IMwForTNavgationItem)
        bindingDelegate = AddressOf TelerikExtensionHelper(Of Telerik.Web.Mvc.UI.TabStripItem).SetContentForAsyncLoading
  
        Dim g = Guid.NewGuid()
        Return helper.Telerik().TabStrip().Name(g.ToString).BindTo(Of IMwForTNavgationItem)(availableItems, bindingDelegate)
    End Function

The bindingdelegate refers to a custom method that does the binding between my model and the model from telerik.
''' <summary>
    ''' Binds a Telerik item to the custom model. This method uses ajax to get the content
    ''' </summary>
    ''' <param name="telerikNavigationItem"></param>
    ''' <param name="mwNavigationItem"></param>
    ''' <remarks></remarks>
    Public Shared Sub SetContentForAsyncLoading(telerikNavigationItem As TabStripItem, mwNavigationItem As IMwForTNavgationItem)
        telerikNavigationItem.Text = mwNavigationItem.Text
        telerikNavigationItem.Enabled = mwNavigationItem.Enabled
        telerikNavigationItem.Visible = True
        If (mwNavigationItem.ContentUrl IsNot Nothing) Then
            telerikNavigationItem.ContentUrl = mwNavigationItem.ContentUrl
        Else
            Throw New ArgumentException("Argument 'mwNavigationItem' has empty property 'ContentURL'. Make sure 'ContentURL' is set or use a different method to bind the model to the Telerik item")
        End If
  
  
        If (Not String.IsNullOrEmpty(mwNavigationItem.ImageUrl)) Then telerikNavigationItem.ImageUrl = mwNavigationItem.ImageUrl
        telerikNavigationItem.Selected = mwNavigationItem.Selected
    End Sub

If you choose not to use your own interface or class as I mentioned for the Content- method, the method  SetContentForAsyncLoading will bind a Telerik class to a Telerik class.

So in the end it all turned out to be simple.

If you have any questions and or remarks on my code, please feel free to post them. I'm always interested in code improvements.

0
A
Top achievements
Rank 1
answered on 14 Sep 2011, 10:21 AM
Hi, I just saw the answer was also given here. :(
Tags
TabStrip
Asked by
A
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
A
Top achievements
Rank 1
Share this question
or