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

Totally lost with grouping a dynamic model and a bar chart

3 Answers 127 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Bil
Top achievements
Rank 1
Bil asked on 05 May 2015, 03:24 PM

Trying to group together data returned from my controller into a chart where items are categorized and grouped by type. Similar to the spain electricty production chart (binding to remote data) or the stock prices (binding to grouped data).

Here's the JSON I've got coming out of the controller

[ { "data" : [ { "client" : "Native-Client/iOS",
          "count" : 7
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 4
        },
        { "client" : "Web-Client",
          "count" : 149
        }
      ],
    "type" : "AddOutageRequest"
  },
  { "data" : [ { "client" : "Web-Client",
          "count" : 161
        },
        { "client" : "Native-Client/iOS",
          "count" : 3
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 2
        }
      ],
    "type" : "AuthorizationFailureRequest"
  },
  { "data" : [ { "client" : "Native-Client/iOS",
          "count" : 9
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 9
        },
        { "client" : "Web-Client",
          "count" : 349
        }
      ],
    "type" : "AuthorizationRequest"
  },
  { "data" : [ { "client" : "Native-Client/iOS",
          "count" : 7
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 6
        },
        { "client" : "Web-Client",
          "count" : 193
        }
      ],
    "type" : "AuthorizationSuccessRequest"
  },
  { "data" : [ { "client" : "Web-Client",
          "count" : 1967
        },
        { "client" : "Native-Client/iOS",
          "count" : 34
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 134
        }
      ],
    "type" : "CurrentOutageRequest"
  },
  { "data" : [ { "client" : "Native-Client/Windows-Phone",
          "count" : 19
        },
        { "client" : "Web-Client",
          "count" : 92
        },
        { "client" : "Native-Client/iOS",
          "count" : 2
        }
      ],
    "type" : "PlannedOutageRequest"
  },
  { "data" : [ { "client" : "Web-Client",
          "count" : 1221
        },
        { "client" : "Native-Client/iOS",
          "count" : 6
        },
        { "client" : "Native-Client/Windows-Phone",
          "count" : 12
        }
      ],
    "type" : "RegionRequest"
  }
]

Each type of request (RegionRequest, AuthorizationRequest, etc.) would be the group. Inside that group the data array contains a series of clients and the count of those requests.

After an hour of mucking about with the wrapper I'm still lost on how to group this data and what goes where. I'm not using a C# model so things like the SeriesDefaults doens't work for me because I can't use a lamdba expression to set it up. I'm in control of all the parts here (markup or JSON) so I can output the JSON in a flatter format or something (although I really don't want to output the complete list of request types as these counts are low but outputting 300+ elements doesn't make sense when I can count it in LINQ on the server side much faster).

So any advice on how the data should be formatted or what the wrapper should look like given this data? Do I have to create a view model to do this (which is fine, I just didn't want to do it for a single chart).

BTW I really struggle with the documentation and examples on the site. They're great but only when they perfectly fit in your scenario. In my case for example I can't find an example where a) it's using the MVC wrapper b) it's binding to remote data c) the data is grouped d) there's no C# model. The descriptions of some of the MVC wrappers is just horrible. For example the description for the CategoryAxis says "Configures the category axis" and the example code in the documentation has an example pulling a single property from a model. Can you configure multiple categories? What if you don't have a model?

I really hope I'm not the only one feeling this. The wrappers are great but I'm constantly having to find snippets and samples on StackOverflow to try to figure out what's going on and how to do things, and usually it results in finding something "close" to what I want that I can tweak and sometimes this means finding a jsfiddle that someone has put together and reverse engineering the html/js to what should be plugged into the MVC wrapper. Yes I know you don't have to use the wrappers but they're there for a purpose and I'd rather try to use them instead of raw markup.

Thanks

3 Answers, 1 is accepted

Sort by
0
T. Tsonev
Telerik team
answered on 07 May 2015, 03:16 PM

Hello Bil,

The data coming from the controller is not a perfect match for the chart. A format similar to the following one will be easier to work with.

Note that that the conversion can happen on the client, but it will be much simpler if the server does it.

[{
  "type" : "AddOutageRequest",
  "client" : "Native-Client/iOS",
  "count" : 7
}, {
  "type" : "AddOutageRequest",
  "client" : "Native-Client/Windows-Phone",
  "count" : 4
}, {
  "type" : "AddOutageRequest",
  "client" : "Web-Client",
  "count" : 149
}, {
  "type" : "AuthorizationFailureRequest",
  "client" : "Native-Client/iOS",
  "count" : 3
}, {
  "type" : "AuthorizationFailureRequest",
  "client" : "Native-Client/Windows-Phone",
  "count" : 2
}, {
  "type" : "AuthorizationFailureRequest",
  "client" : "Web-Client",
  "count" : 161
}]

What you mean by "group" is a category to the chart. Hence we need to ensure that each data point will land in the correct category.

.Series(series => {
  series.Column(model => model.count, categoryExpression: model => model.type);
})

We now have 3 points that point to each category so the chart has no choice, but to compute an aggregate. This is the max value by default. See AggregateChart.png for example. 

What we really want to do is to have one bar for each client. In other words we want to have a separate series for each client. We can group the data source to achieve this effect.

.DataSource(dataSource => dataSource
  .Read(read => read.Action("Data", "Chart"))
  .Group(group => group.Add(model => model.client))
)

I've also made the value axis logarithmic to give us better view into the smallest values.

.ValueAxis(axis => axis.Logarithmic().Max(1000))

The chart now looks like GroupedChart.png.

The documentation can definitely be improved. This is something that we look forward to do.

I hope this helps.

T. Tsonev
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
0
Bil
Top achievements
Rank 1
answered on 07 May 2015, 06:56 PM
Yes, the results you posted are exactly what I'm looking for. The only thing is you're using lambda expressions to do the markup. So do I have to create a model for this to work? If not, how would the markup be with raw JSON (but using the MVC wrapper) since it won't just accept a string name for the property.
0
T. Tsonev
Telerik team
answered on 11 May 2015, 12:53 PM

Hello Bil,

Using a model class will be the most convenient, but you can set model field names directly as well:

.Group(g => g.Add("client", typeof(String)))

series.Column("count", categoryMemberName: "type");

I hope this helps.

Regards,
T. Tsonev
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
Tags
Chart
Asked by
Bil
Top achievements
Rank 1
Answers by
T. Tsonev
Telerik team
Bil
Top achievements
Rank 1
Share this question
or