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

How does the signalr chart client needs refresh?

11 Answers 274 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Kelso
Top achievements
Rank 1
Kelso asked on 22 Oct 2014, 06:39 PM
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>

11 Answers, 1 is accepted

Sort by
0
Kelso
Top achievements
Rank 1
answered on 22 Oct 2014, 06:41 PM
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
0
T. Tsonev
Telerik team
answered on 27 Oct 2014, 08:58 AM
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.

 
0
Kelso
Top achievements
Rank 1
answered on 27 Oct 2014, 06:19 PM
Test
0
Kelso
Top achievements
Rank 1
answered on 27 Oct 2014, 06:35 PM
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.
0
T. Tsonev
Telerik team
answered on 30 Oct 2014, 09:29 AM
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.

 
0
Kelso
Top achievements
Rank 1
answered on 05 Nov 2014, 04:11 PM
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.
0
Kelso
Top achievements
Rank 1
answered on 05 Nov 2014, 06:31 PM
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();
        }





0
T. Tsonev
Telerik team
answered on 07 Nov 2014, 08:46 AM
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.

 
0
Kelso
Top achievements
Rank 1
answered on 07 Nov 2014, 02:39 PM
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.
0
T. Tsonev
Telerik team
answered on 11 Nov 2014, 09:09 AM
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.

 
0
Kelso
Top achievements
Rank 1
answered on 11 Nov 2014, 04:20 PM
Thank you that would be greatly appreciated!
Tags
Chart
Asked by
Kelso
Top achievements
Rank 1
Answers by
Kelso
Top achievements
Rank 1
T. Tsonev
Telerik team
Share this question
or