How does the signalr chart client needs refresh?

12 posts, 0 answers
  1. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 22 Oct 2014 Link to this post

    ok so I have created a chart, that takes data from a MVC action method and populates a chart, in your example here http://dojo.telerik.com/@tsvetomir/UvON You have autosync set to true, but where is the push coming from? How do I send the updated information? My chart loads Initially but does not change when any of the status' change.

    Code for chart: 
    <script>
        var connection = $.hubConnection();
        var hub = connection.createHubProxy("centralHub");
        connection.logging = true;
        var hubPromise = connection.start();

    </script>
    @{

        double[] clockins = new double[5];
        double[] breaks = new double[5];
        double[] lunch = new double[5];
        if (Model != null)
        {
            foreach (var item in Model)
            {
                switch (item.SiteName)
                {
                    case "Mabel":
                        switch (item.TypeName)
                        {
                            case "ClockIn":
                                clockins[0] = item.Count;
                                break;
                            case "Break":
                                breaks[0] = item.Count;
                                break;
                            case "Lunch":
                                lunch[0] = item.Count;
                                break;
                        }
                        break;
                    case "Harp":
                        switch (item.TypeName)
                        {
                            case "ClockIn":
                                clockins[1] = item.Count;
                                break;
                            case "Break":
                                breaks[1] = item.Count;
                                break;
                            case "Lunch":
                                lunch[1] = item.Count;
                                break;
                        }
                        break;
                    case "Pendleton":
                        switch (item.TypeName)
                        {
                            case "ClockIn":
                                clockins[2] = item.Count;
                                break;
                            case "Break":
                                breaks[2] = item.Count;
                                break;
                            case "Lunch":
                                lunch[2] = item.Count;
                                break;
                        }
                        break;
                    case "Granite":
                        switch (item.TypeName)
                        {
                            case "ClockIn":
                                clockins[3] = item.Count;
                                break;
                            case "Break":
                                breaks[3] = item.Count;
                                break;
                            case "Lunch":
                                lunch[3] = item.Count;
                                break;
                        }
                        break;
                    case "HQ":
                        switch (item.TypeName)
                        {
                            case "ClockIn":
                                clockins[4] = item.Count;
                                break;
                            case "Break":
                                breaks[4] = item.Count;
                                break;
                            case "Lunch":
                                lunch[4] = item.Count;
                                break;
                        }
                        break;
                }
            }
        }
    }
    <body>
        <div class="k-chart">
            @(Html.Kendo().Chart<TcStatusChartData>()
                  .Name("chart")
                  .Title("Agents by status")
                  .Legend(legend => legend
                      .Position(ChartLegendPosition.Bottom)
                  )
                  .SeriesDefaults(seriesDefaults =>
                      seriesDefaults.Bar().Stack(ChartStackType.Normal)
                  )
                  .Series(series =>
                  {
                      series.Column(new double[] { clockins[0], clockins[1], clockins[2], clockins[3], clockins[4] }).Stack(ChartStackType.Normal).Name("Clocked In");
                      series.Column(new double[] { breaks[0], breaks[1], breaks[2], breaks[3], breaks[4] }).Stack(ChartStackType.Normal).Name("On Break");
                      series.Column(new double[] { lunch[0], lunch[1], lunch[2], lunch[3], lunch[4] }).Stack(ChartStackType.Normal).Name("On Lunch");
                  }).SeriesColors("#33FF33", "#CCFF33", "#FF9933")
                  .CategoryAxis(axis => axis
                      .Categories("Mabel", "Harp", "Pendleton", "Granite", "HQ")
                      .MajorGridLines(lines => lines.Visible(false))

                  )
                  .ValueAxis(axis => axis
                      .Numeric()
                      .Labels(labels => labels.Format("{0}"))
                      .Max(100)
                      .Line(line => line.Visible(false))
                      .MajorGridLines(lines => lines.Visible(true))
                  ).DataSource(datasource => datasource
                      .SignalR().AutoSync(true)

                      .Transport(tr => tr.Promise("hubPromise")
                          .Hub("hub")
                          .Server(server => server
                              .Read("chart_Read")
                              .Update("update")
                              .Destroy("desstroy")
                              .Create("create")))
                  )
                  .Tooltip(tooltip => tooltip
                      .Visible(true)
                      .Template("#= series.name #: #= value #")
                  )
            )
        </div>
    </body>

  2. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 22 Oct 2014 in reply to Kelso Link to this post

    Sorry the title is missing a word, how does the client know it needs to refresh data? specifically how it relates to the autosync property
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. T. Tsonev
    Admin
    T. Tsonev avatar
    2772 posts

    Posted 27 Oct 2014 Link to this post

    Hello,

    Please accept my apologies for the delayed response.

    The Dojo snippet receives the push updates from the SignalR Grid demo.
    The SignalR service itself is hosted on our demo site.

    Currently your code declares series with static model binding. You need to convert them to data source binding in order for the updates to work:
    .Series(series => {
        series.Column(model => model.MyValueField).Stack(ChartStackType.Normal).Name("Clocked In");


    Same goes for the axis categories.

    See the remote binding demo for example.

    We'll convert this snippet to a proper MVC demo and include it with the Q3 release.
    Apologies for the caused inconvenience.

    Regards,
    T. Tsonev
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 27 Oct 2014 Link to this post

    Test
  6. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 27 Oct 2014 in reply to T. Tsonev Link to this post

    The syntax you suggest is not working, it does not serialize the data correctly, I have tried to post the code for the issue 3 times, but I get an error trying to post it and its starting to annoy me. the bottom line is that lamba expression does not serialize the data correctly, this is probably related the to previous issue I had with your mvc implementation I posted about. your answer on the using the remote data binding is not clear, how do I use remote binding to a mvc method call on a signalr hub implementation? The Signalr transport object does not have a read method and the signalr version of read only takes a string. So I am very confused about how your signalr implementation updates.
  7. T. Tsonev
    Admin
    T. Tsonev avatar
    2772 posts

    Posted 30 Oct 2014 Link to this post

    Hello,

    I've prepared an MVC version of our sample page. The chart seems to update properly.
    Can you spot any major differences with your code?

    Regards,
    T. Tsonev
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  8. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 05 Nov 2014 in reply to T. Tsonev Link to this post

    Sorry it took me a while to get back to this, the only difference that I have noticed is 

                series.Line(
                    model => model.UnitPrice,
                    categoryExpression: model => model.ProductName
                );

    categoryExpression  is not in any documentation that I have seen. and this is the first time I have seen it in any demo or example.


    How is signalr updating the data from your remote binding, is your grid calling an mvc action method? is grid update method updating the data and broadcasting it to the chart client? you have alot of your implementation hidden, so I do not know how your grid is actually syncing the data with the chart.
  9. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 05 Nov 2014 in reply to T. Tsonev Link to this post

    The best suggestion I can make here is to do a simple project that uses a stacked bar, that gets its data from a hub push, using the lambda expression syntax. 

    If I try to use .Categories(model => model.SiteNames) I get [object],[object] If I populate a TcStatusChartData object and return it to the view from the mvc controller method I can use .Categories(Model.SiteNames) and this will work because I initially populating the data from the controller and not the updateChart method on the hub.

    If I use this way of populating the chart, and I force the chart datasource to do a read by calling the client method on this page to make it call the server method, it fires my hub method and returns the data but the chart does not update. not to mention this is really bad way to do this, considering signalr is a push technology.

    Here is my code for the view.

    @using TimeClockService.ViewModels
    @model  TcStatusChartData

    @{

        ViewBag.Title = "View";
    }

    <h2>View</h2>
    <script>
        var connection = $.hubConnection();
        var hub = connection.createHubProxy("centralHub");
        connection.logging = true;
        var hubPromise = connection.start();

    </script>
    <body>
        <div class="k-chart">
            @(Html.Kendo().Chart<TcStatusChartData>()
                  .Name("chart")
                  .Title("Agents by status")
                  .Legend(legend => legend
                      .Position(ChartLegendPosition.Bottom)
                  )
                  .SeriesDefaults(seriesDefaults =>
                      seriesDefaults.Bar().Stack(ChartStackType.Normal)
                  )
                  .Series(series =>
                  {
                      series.Column(model => Model.Clockins).Stack(ChartStackType.Normal).Name("Clocked In").Spacing(0);
                      series.Column(model => Model.Breaks).Stack(ChartStackType.Normal).Name("On Break").Spacing(0);
                      series.Column(model => Model.Lunches).Stack(ChartStackType.Normal).Name("On Lunch").Spacing(0);
                  }).SeriesColors("#33FF33", "#0080FF", "#FF9933")
                  .CategoryAxis(axis => axis
                      .Categories(Model.SiteNames)
                      .Labels(labels => labels.Rotation(-90))
                      .MajorGridLines(lines => lines.Visible(false))

                  )
                  .ValueAxis(axis => axis
                      .Numeric()
                      .Labels(labels => labels.Format("{0}"))
                      .Max(100)
                      .Line(line => line.Visible(false))
                      .MajorGridLines(lines => lines.Visible(true))
                  ).DataSource(datasource => datasource
                      .SignalR()
                      .AutoSync(true)
                      .Transport(tr => tr.Promise("hubPromise")
                          .Hub("hub")
                          .Server(server => server
                              .Read("updateChart")
                              .Update("update")
                              .Destroy("desstroy")
                              .Create("create"))
                          .Client(client => client.Read("updateChart")))
                  )
                  .Tooltip(tooltip => tooltip
                      .Visible(true)
                      .Template("#= series.name #: #= value #")
                  )
                  )
        </div>
    </body>
    <script>
        hub.on("updateChart", function () {
            $("#chart").data("kendoChart").dataSource.read();
        });
    </script>

    here is the code for my controller

           public ActionResult Chart()
            {
                //TcStatusChartData crtData = new TcStatusChartData();
                //crtData = _userService.GetTcStatusData();
                //return View(crtData);
            }

    code for my populating the object

          public TcStatusChartData GetTcStatusData()
            {
                try
                {

                    //ApplicationDbContext context = new ConnectionHelper().Context;
                    
                    List<Site> sites = _site.GetAll();
                    List<string> siteNames = new List<string>();
                    int[] clockins = new int[sites.Count];
                    int[] breaks = new int[sites.Count];
                    int[] lunches = new int[sites.Count];
                    TcStatusChartData chartData = new TcStatusChartData();
                    int i = 0;
                    foreach (Site s in sites)
                    {
                        siteNames.Add(s.SiteName);
                        clockins[i] = _timeClock.GetAll(x => x.ClockOutDate == null && x.Site.Id == s.Id && x.Type.Id == 1).Count;
                        breaks[i] = _timeClock.GetAll(x => x.ClockOutDate == null && x.Site.Id == s.Id && x.Type.Id == 2).Count;
                        lunches[i] = _timeClock.GetAll(x => x.ClockOutDate == null && x.Site.Id == s.Id && x.Type.Id == 3).Count;
                        i++;
                    }
                    chartData.SiteNames = siteNames;
                    chartData.Clockins = clockins;
                    chartData.Breaks = breaks;
                    chartData.Lunches = lunches;
                    return chartData;
                }
                catch (Exception ex)
                {
                    var message = ex.GetBaseException().Message;
                    return new TcStatusChartData();
                }
            }

    and finally hub method

            public TcStatusChartData UpdateChart()
            {
                return _userService.GetTcStatusData();
            }





  10. T. Tsonev
    Admin
    T. Tsonev avatar
    2772 posts

    Posted 07 Nov 2014 Link to this post

    Hi,

    The SignalR updates only go as far as to update the data source. It has no connection with the view model whatsoever.
    In order for this to work the data should be return a collection of model objects such as:
    class ChartModel
    {
        public string SiteName { get; set; }
        public int Clockins { get; set; }
        public int Breaks { get; set; }
        public int Lunches { get; set; }
    }


    Then all series can be bound as:
    @(Html.Kendo().Chart<ChartModel>()
      .DataSource(datasource => datasource.SignalR()...)
      .Series(series =>
        series.Column(model => Model.Clockins)...
        series.Column(model => Model.Breaks)...
        series.Column(model => Model.Lunches)...
      )

    Same for the category axis:
    CategoryAxis(axis => axis
        .Categories(model => model.SiteName)


    This is pretty much the same as remote binding, but with SignalR on top.

    I hope this helps.

    Regards,
    T. Tsonev
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  11. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 07 Nov 2014 in reply to T. Tsonev Link to this post

    Your stacked bar example makes things very unclear then, because you are supplying data points across the grouping object, while to do it as mvc the data points are kept in encapsulated in a single object within a collection. 

    Your stacked bar has this series.

    .Series(series =>
    {
    series.Bar(new double[] { 40, 32, 34, 36, 45, 33, 34, 83, 36, 37, 44, 37, 35, 36, 46 }).Name("Gold Medals").Color("#f3ac32");
    series.Bar(new double[] { 19, 25, 21, 26, 28, 31, 35, 60, 31, 34, 32, 24, 40, 38, 29 }).Name("Silver Medals").Color("#b8b8b8");
    series.Bar(new double[] { 17, 17, 16, 28, 34, 30, 25, 30, 27, 37, 25, 33, 26, 36, 29 }).Name("Bronze Medals").Color("#bb6e36");
    })
    .CategoryAxis(axis => axis
    .Categories("1952", "1956", "1960", "1964", "1968", "1972", "1976", "1984", "1988", "1992", "1996", "2000", "2004", "2008", "2012")
    .MajorGridLines(lines => lines.Visible(false))
    )

    but mvc requires the object structure that you are saying which is where the confusion is, and every single time I have an issue its because your documentation is all over the place, and the examples are never consistent, with the your documentation.

     This wasted way too much of my time, I used a different library and had the whole thing done in a matter of hours, I wasted that much time just trying to discern the difference between your examples and your documentation.
  12. T. Tsonev
    Admin
    T. Tsonev avatar
    2772 posts

    Posted 11 Nov 2014 Link to this post

    Hi,

    Indeed some of the examples use static binding, but this is simply serialized in-line.
    Remote binding usually requires using a model and binding to its fields. This includes SignalR as well.

    We'll try to clear this in the documentation by listing the accepted data formats for each series type.
    Apologies for the caused inconvenience.

    Regards,
    T. Tsonev
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  13. Kelso
    Kelso avatar
    36 posts
    Member since:
    Dec 2013

    Posted 11 Nov 2014 in reply to T. Tsonev Link to this post

    Thank you that would be greatly appreciated!
Back to Top
UI for ASP.NET MVC is VS 2017 Ready