MVC: Unable to add a chart to tabpanel

  1. #1

    MVC: Unable to add a chart to a tabpanel

    Hi,

    I evaluate 4.0.0 RC. When I add a partialview with a chart to a tabpanel I get an error.
    Everything is correct when I use Html.RenderPartial for the partialview.

    What am I doing wrong or is it a bug?

    thanks,
    Martin


    The error message is:

    [TokenNotUniqueException: Token is not unique
    -------------------
    ID = \
    TagName = anchor
    Match = <#:anchor id="id9a948acade8bbf9f_ClientInit" />
    ]
    Transformer.NET.Token.ParseAnchors() +355
    Transformer.NET.TextTransformer.Parse(List`1 tokensType, Dictionary`2 variables) +669
    Transformer.NET.TextTransformer.Transform(List`1 tokensType, Dictionary`2 variables) +31
    Transformer.NET.TextTransformer.Transform(List`1 tokensType) +25
    Transformer.NET.TextTransformer.Transform() +40
    Ext.Net.ExtNetTransformer.Transform(String text) +150
    Ext.Net.InitScriptFilter.Transform() +72
    Ext.Net.InitScriptFilter.Flush() +76
    System.Web.HttpWriter.FilterIntegrated(Boolean finalFiltering, IIS7WorkerRequest wr) +9641741
    System.Web.HttpResponse.FilterOutput() +104
    System.Web.CallFilterExecutionStep.System.Web.Http Application.IExecutionStep.Execute() +58
    System.Web.HttpApplication.ExecuteStep(IExecutionS tep step, Boolean& completedSynchronously) +69
    Controller Snippet:

            public ActionResult BasicChart()
            {
                return PartialView(model.ChartModel);
            }
    
            public ActionResult Chart()
            {
                return View(model.ChartModel);
            }
    Partial View with Chart:

    @model List<Ext.Net.MVC.Examples.BasicChartModel>
    
    @Html.X().ResourceManager()
    
    @{
        ViewBag.Title = "Line Chart - Ext.NET MVC Examples";
        var X = Html.X();
    }
    
    @(X.CartesianChart()
        .Animation(false)
        .FlipXY(false)
        .Height(500)
        .Store(X.Store()
            .Data(Model)
            .Model(X.Model()
                .Fields(
                    X.ModelField().Name("Name"),
                    X.ModelField().Name("Data1")
                )
            )
        )
        .Axes(
            X.NumericAxis()
                .Fields("Data1")
                .Position(Position.Left)
                .Grid(true)
                .Maximum(100)
                .Renderer(r => r.Handler = "return label.toFixed(0) + '%';"),
    
            X.CategoryAxis()
                .Position(Position.Bottom)
                .Fields("Name")
                .Grid(true)
        )
        .Series(
        X.LineSeries()
            .XField("Name")
            .YField("Data1")
            .Smooth(3)
            .HighlightConfig(X.Sprite().Radius(7))
            .Marker(X.CircleSprite().Radius(4).LineWidth(0))
        )
    )
    View with Tab:

    @model List<Ext.Net.MVC.Examples.BasicChartModel>
    
    @{
        ViewBag.Title = "Chart";
        Layout = "~/Views/Shared/_Layout.cshtml";
        var X = Html.X();
    }
    
    
    @(X.TabPanel().ActiveTabIndex(0)
                      .Width(1000)
                      .Height(350)
                      .Items(X.Panel().Title("Chart 1")
                                      .AutoScroll(true)
                                      .Html(Html.Partial("BasicChart", Model).ToHtmlString()),
    
                            X.Panel().Title("Chart 2")
                                      .AutoScroll(true)
                                      .Html("Hello World")
                  )                
    )

    Working View:

    @model List<Ext.Net.MVC.Examples.BasicChartModel>
    
    @{
        ViewBag.Title = "Chart";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    @{Html.RenderPartial("BasicChart", Model);}
    When I use
    .Loader(X.ComponentLoader().Url(Url.Action("BasicChart", Model))
    instead of
    .Html(Html.Partial("BasicChart", Model).ToHtmlString())
    there is no error, but the tab is empty.
    Last edited by marjot2112; Mar 24, 2016 at 4:26 PM.
  2. #2
    Hello @marjot2112! Welcome to Ext.NET forums!

    I think that your Html.Partial() method is not going to work anyway. But when you use Loader approach, you should be using it in ScriptMode.

    Give this example a look: Dynamic Partial Rendering - Partial Content. There are other usages of partial rendering next to that example that could be useful for you.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Hello fabricio.murata,

    thanks for your answer. Unfortunately, the answer does not help me.

    My goal is to present charts in different tabs, this could be done with static or dynamic partial rendering.

    I tried different approaches (based on the example explorer) but all failed. I was successful to load my partial views into the tabs without charts but if I added a chart, I get an error message or the chart was not shown.

    I recognized that the ResourceManager and the LoadMode of the Loader has an influence on the behavior, but I can’t find a sufficient documentation of both. It is hard way to evaluate a library by try and error.

    I only found the example explorer and a poor api documentation, is there any further documentation of EXT.NET MVC available?

    May you can provide a simple example with two tabs, and each tab contains a partial view with a chart, that will help me a lot.
    Last edited by marjot2112; Mar 29, 2016 at 11:25 AM.
  4. #4
    Hello @marjot2112!

    Can you link where did you find the poor API documentation you mentioned? Actually Ext.NET is a framework written on top of ExtJS so the vast majority of our API reflects the Sencha's ExtJS, which extensive API documentation can be found here: Sencha Documentation on ExtJS 6.0.1.

    Also, we try to provide best (although it can not be perfect at the moment) IntelliSense support and documentation, with descriptive texts.

    This is my personal thought: The examples are the absolute starting point to understand how a grid or another component should be built. From that point (after exploring examples with different usages), to get specific behavior then you explore options with Intellisense help, then refer to API and in the most specific approaches, you may end up needing to write JavaScript code and/or override. It is usually common to write some helper JavaScript code, specially when you want the page not sending lots of postback which could clobber the server and make the user experience uncomfortable.

    Next I will check if there's something that impedes to add a graph from a partial view into a tab and share the code with you if not.
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Hello again, to the sample you requested:

    - It will have two tabs
    - Two different graphs, one in each tab
    - For simplicity I let the features to a minimum
    - I could have done some code reuse in the get data, but left two specific actions and two specific partial views by purpose to illustrate the functionality.
    - I have prefixed "c60766" with the forum thread ID to bind the example to this forum thread in my local project, so you are going to see this everywhere.

    Controller:
    using Ext.Net.MVC;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace ExtNetPlaygroundMVC_current.Controllers
    {
        public class issuesController : Controller
        {
            public ActionResult c60766_Index()
            {
                return View();
            }
    
            public StoreResult c60766_GetChart1Data()
            {
                return new StoreResult(new List<object>()
                {
                    new { Name = "a", Value = 1 },
                    new { Name = "b", Value = 2 },
                    new { Name = "c", Value = 3 },
                    new { Name = "d", Value = 4 },
                    new { Name = "e", Value = 5 }
                });
            }
    
            public Ext.Net.MVC.PartialViewResult c60766_PV1(string containerId)
            {
                return new Ext.Net.MVC.PartialViewResult
                {
                    ViewName = "c60766_pv1",
                    ContainerId = containerId,
                    RenderMode = Ext.Net.RenderMode.AddTo,
                    WrapByScriptTag = false
                };
            }
    
            public Ext.Net.MVC.PartialViewResult c60766_PV2(string containerId)
            {
                return new Ext.Net.MVC.PartialViewResult
                {
                    ViewName = "c60766_pv2",
                    ContainerId = containerId,
                    RenderMode = Ext.Net.RenderMode.AddTo,
                    WrapByScriptTag = false
                };
            }
    
            public StoreResult c60766_GetChart2Data()
            {
                return new StoreResult(new List<object>()
                {
                    new { Name = "x", Value = 3 },
                    new { Name = "y", Value = 5 },
                    new { Name = "z", Value = 1 },
                    new { Name = "k", Value = 2 },
                    new { Name = "m", Value = 4 }
                });
            }
    
        }
    }
    Main view c60766_Index.cshtml:
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>c60766_index</title>
    </head>
    <body>
        <div>
            @(Html.X().ResourceManager())
    
            @(Html.X().TabPanel()
              .Title("Tab Panel with partial view Graphs")
              .Width(800).Height(600)
              .Items(
                Html.X().Panel().ID("tab1")
                .Title("Tab1")
                .Layout(LayoutType.Fit)
                .Loader(
                    Html.X().ComponentLoader()
                    .Url(Url.Action("c60766_PV1"))
                    .Mode(LoadMode.Script)
                    .Params(new { containerId = "tab1" })
                ),
                Html.X().Panel().ID("tab2")
                .Title("Tab2")
                .Layout(LayoutType.Fit)
                .Loader(
                    Html.X().ComponentLoader()
                    .Url(Url.Action("c60766_PV2"))
                    .Mode(LoadMode.Script)
                    .Params(new { containerId = "tab2" })
                )
    
              )
            )
        </div>
    </body>
    </html>
    Partial view 1 (chart on tab1), c60766_PV1.cshtml:
    @(
        Html.X().CartesianChart()
        .Store(
            Html.X().Store().ID("storeChart1")
            .Model(
                Html.X().Model().Fields("Name", "Value")
            )
            .Proxy(
                Html.X().AjaxProxy().Url(Url.Action("c60766_GetChart1Data"))
                    .Reader(Html.X().JsonReader().RootProperty("data"))
            )
            .Data(Model)
        )
        .Axes(
            Html.X().NumericAxis()
                .Position(Position.Left)
                .Fields("Value")
                .Grid(true)
                .Title("Value"),
            Html.X().CategoryAxis()
                .Fields("Name")
                .Title("Name")
        )
        .Series(
            Html.X().BarSeries()
            .XField("Name")
            .YField("Value")
        )
    )
    Partial view 2 (chart on tab2), c60766_PV2.cshtml:
    @(
     Html.X().CartesianChart()
        .Store(
            Html.X().Store().ID("storeChart2")
            .Model(
                Html.X().Model().Fields("Name", "Value")
            )
            .Proxy(
                Html.X().AjaxProxy().Url(Url.Action("c60766_GetChart2Data"))
                    .Reader(Html.X().JsonReader().RootProperty("data"))
            )
            .Data(Model)
        )
        .Axes(
            Html.X().NumericAxis()
                .Position(Position.Left)
                .Fields("Value")
                .Grid(true)
                .Title("Value"),
            Html.X().CategoryAxis()
                .Fields("Name")
                .Title("Name")
        )
        .Series(
            Html.X().BarSeries()
            .XField("Name")
            .YField("Value")
        )
    )
    This is pretty much the merge of the examples:
    - Dynamic Partial Rendering - Partial Items
    - Charts - Column - Basic

    In a simplified way.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  6. #6
    Thanks for your extensive help. Your example works fine for me.
    At first sight the use of the Ext.Net.MVC.PartialViewResult instead of the PartialView was the missing puzzle piece.

    What I meant with poor documentation is the Ext.Net API documentation. It is only an alphabetically sorted flat list of classes with a minimum of explanation. A structure similar to the ExtJS API documentation would be helpful.

    May after working some weeks with the Ext.Net library the approach to use the Sencha ExtJS API Documentation is totally sufficient.

    What I’m missing as an absolute beginner is a getting started documentation of the Ext.Net library. How the library is intended to use, and some explanations with examples how I can map the Sencha ExtJS API to the Ext.Net API.

    After that the Example Explorer gives a good overview over the extensive Capabilities of the library.
  7. #7
    Thanks for the suggestions! We really appreciate user feedback so we can improve our introductory experience to new users!

    By the way, we do have a getting started section on our examples explorer where we try to address the issues you pointed as an absolute beginner.

    Did you browse those sections on the examples explorer? (http://examples4.ext.net/#/Getting_S...nent_Overview/ and the other two neighbor entries: Installation and Overview).

    If you didn't browse those getting started sections, did they help you on the issues (some or all) you pointed? Suggestions and feedback are welcome!

    Back to the API, probably you see just an alphabetical list of entries in the API reference because we had to make a choice when designing Ext.NET:

    - Should we have the user to clobber the code file with using statements for all namespaces, make sub-classes so they have to type longer names (or just, again rely on using aliases), or flatten everything on the same name space so a single namespace reference would do for all the application?

    We chose the latter believing it would be the option bringing the most simplicity, readability and also productivity in an Ext.NET, C# (WebForms or MVC) point of view, although this would hurt a little mapping from Ext.NET to ExtJS. We left a reference though by string object.instanceOf() on any Ext.NET classes with the full class name. This is mostly useful for people with Ext.NET source code access (premium users) as when navigating for the definition of the InstanceOf() method the user would be presented with the textual representation of the ExtJS class name.

    Thanks again for the feedback and hope some of this clarifies your questions about Ext.NET.
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Replies: 0
    Last Post: Dec 02, 2015, 5:00 AM
  2. [CLOSED] Unable to get Chart Mouse events working
    By Woodhac in forum 3.x Premium Help
    Replies: 6
    Last Post: Apr 29, 2015, 6:10 AM
  3. Replies: 2
    Last Post: Nov 08, 2013, 2:14 PM
  4. Unable to get the PopUp Dynamic Chart
    By nagesh in forum 2.x Help
    Replies: 6
    Last Post: Dec 05, 2012, 5:42 AM
  5. Replies: 2
    Last Post: Mar 29, 2010, 10:04 AM

Tags for this Thread

Posting Permissions