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

Dynamically created Series with Multiple Axis

12 Answers 56 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Lee
Top achievements
Rank 1
Veteran
Lee asked on 18 Jun 2018, 09:33 AM

Hi,

I've got the chart how i would like it apart form having multiple category axis, please see attached image.

As you can see i have one CategoryAxis working the persons name, ideally i'd like each Column name to appear above that.(series.stack)

Here's my current code:

@(Html.Kendo().Chart()
                     .Name("chart")
                     .Title("Project Management")
                     .Legend(legend => legend
                         .Position(ChartLegendPosition.Top)
                     )
                     .SeriesDefaults(seriesDefaults =>
                         seriesDefaults.Column().Stack(true)
                     )
                     .Series(series =>
                     {
                         foreach (var def in Model.Series)
                         {
                             series.Column(def.Data).Name(def.Name).Stack(def.Stack);
                         }
                     })
                     .SeriesColors(Colours.Blue, Colours.Orange, Colours.Grey, Colours.Yellow, Colours.LightBlue, Colours.Green)
                     // This should be the Stack Name (Overhead)
                     .CategoryAxis(axis => axis.Labels(l => l.Rotation(90).Template("#= series.stack #")))
                     // This should be the Persons Name (FullName)
                     .CategoryAxis(axis => axis.Categories(Model.Categories))
                     .Tooltip(tooltip => tooltip
                         .Visible(true)
                         .Template("#= series.name #: #= kendo.format('{0:N2}', value) #")
                     )
               )

 

What's the easiest way to achieve this? This is based off of your example project: https://github.com/telerik/ui-for-aspnet-mvc-examples/tree/master/chart/dynamic-series

Thanks,
Lee.

 

12 Answers, 1 is accepted

Sort by
0
Accepted
Tsvetina
Telerik team
answered on 20 Jun 2018, 08:14 AM
Hello Lee,

Showing each series stack name in a CategoryAxis would not be possible because the number of stacks are determined on the fly in this case and the category axis needs to have a list of categories set. What I can suggest is to use the label of the bottom series in each stack to display the stack value and offset it to the bottom of the Chart using a margin setting:
@model DynamicSeries.Models.MyViewModel
 
@(Html.Kendo().Chart()
      .Name("Chart")
      .Series(series => {
          foreach (var def in Model.Series) {
              series.Column(def.Data).Name(def.Name).Stack(def.Stack)
                 .Labels(lbl=>lbl
                 .VisibleHandler("showLabel")
                 .Position(ChartBarLabelsPosition.InsideBase)
                 .Margin(0, 0, -20, 0)
                 .Template("#:series.stack#")
                 .Background("transparent")
                 );
          }
      })
      .CategoryAxis(axis => axis
         .Labels(lbl=>lbl.Visible(false)) // empty category axis to look like the labels are rendered in it
      )
      .CategoryAxis(axis => axis
         .Categories(Model.Categories)
      )
  )
<script>
    var lastStack;
    function showLabel(e) {
        // show label only for first series in each stack
        var isInNewStack = e.series.stack != lastStack;
        lastStack = e.series.stack;
        return isInNewStack;
    }
</script>

You can see what the result looks like in the attached image. Is this the look that you are trying to achieve?

Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Lee
Top achievements
Rank 1
Veteran
answered on 20 Jun 2018, 08:17 AM

Hi Tsvetina,

From your image that looks exactly like what i need. Again you provide a great answer!

Thank you very much!

0
Lee
Top achievements
Rank 1
Veteran
answered on 20 Jun 2018, 09:41 AM
Ah it nearly works see attached image.
0
Tsvetina
Telerik team
answered on 20 Jun 2018, 11:24 AM
Hello Lee,

It looks like the VisibleHandler function does not produce the expected result on your side. Can you share your code, including the JavaScript to determine the labels visibility? You can put a breakpoint in the function and debug it to see why it always returns true. One guess would be if you have not declared the global variable used to keep the stack name of the previous series:
<script>
    var lastStack; // => global variable needed to store the name of the previous series stack, so we can show the label if the current series belongs to a new stack
    function showLabel(e) {
        // show label only for first series in each stack
        var isInNewStack = e.series.stack != lastStack;
        lastStack = e.series.stack;
        return isInNewStack;
    }
</script>


Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Lee
Top achievements
Rank 1
Veteran
answered on 21 Jun 2018, 07:06 AM

Hi Tsvetina,

I have copied it like you had it:

<script>
    var lastStack;
    function showLabel(e)
    {
        // show label only for first series in each stack
        var isInNewStack = e.series.stack != lastStack;
        console.log(e.series.stack + ' != ' + lastStack + ' = ' + isInNewStack);
        lastStack = e.series.stack;
 
        return isInNewStack;
    }
</script>

 

I added some logging as you can see and the result is this:

Chargeable != undefined = true
Overhead != Chargeable = true
Sick Leave != Overhead = true
Annual Leave != Sick Leave = true
RDO != Annual Leave = true
Chargeable != RDO = true
Overhead != Chargeable = true
Sick Leave != Overhead = true
[...]

 

Lee

 

0
Lee
Top achievements
Rank 1
Veteran
answered on 21 Jun 2018, 07:25 AM

I have managed to get it to work using this:See attached Photo

<script>
    var lastStack;
    function showLabel(e)
    {
        // show label only for first series in each stack
        var isInNewStack = e.series.stack !== lastStack
            && (e.index >= 0 && e.index < e.series.data.length)
            && (e.series.index >= 0 && e.series.index < e.series.data.length);
 
        lastStack = e.series.stack;
 
        return isInNewStack;
    }
</script>

 

My only remaining question is how can i make the category axis higher so i can fit them in vertically and align them? (refer to image again)

 

0
Lee
Top achievements
Rank 1
Veteran
answered on 21 Jun 2018, 07:48 AM

I also noticed if i click on of the key items off the label disappears so maybe my code isn't that great.

You can see the labels have shifted to the left when i unselect "Chargeable - 2017-Jul"

0
Tsvetina
Telerik team
answered on 25 Jun 2018, 08:44 AM
Hi Lee,

My logic also does not cover scenarios where series are hidden dynamically. For this scenario, the following code looks to be working well in my test page:
<script>
    function showLabel(e) {
        var chart = $("#Chart").data("kendoChart"),
            index = e.series.index,
            stack = e.series.stack;
        if (index == 0 ||
            (index != 0 && chart.options.series[index - 1].visible == false) ||
            (index != 0 && stack != chart.options.series[index - 1].stack)) {
            return true;
        }
        return false;
    }
</script>

Could you try it and let me know if you find cases where it fails?

Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Lee
Top achievements
Rank 1
Veteran
answered on 25 Jun 2018, 09:33 AM

Hi Tsvetina,

Thanks again for helping, but that also doesn't work (well it does by displaying the label when i hide a series but, it still displays a label for all series not just the bottom).

I've created a dojo for you maybe to make it easier?  https://dojo.telerik.com/afOHUHub

Thanks,
Lee.

0
Tsvetina
Telerik team
answered on 27 Jun 2018, 08:38 AM
Hi Lee,

Thank you for the example. I see now what the difference is. In your scenario, the series from one and the same stack are not created one after the other, so the logic to check if the previous series belongs to another stack in order to display the label always returns true. With such order of the series, I do not think the suggested solution could be adjusted to work.

However, if it is possible to order the data by Stack before returning it to the view, the problem should be resolved. Could you try ordering the Model.Series collection by the Stack field in the controller?

Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Lee
Top achievements
Rank 1
Veteran
answered on 27 Jun 2018, 08:52 AM

Hi Tsvetina,

Great, that fixed it! Now i guess i just need to know how i can make the empty categoryAxis higher so i can fit the labels in at 90 degrees.

(See attached image)

Again thank you for you fantastic support!!

 

0
Tsvetina
Telerik team
answered on 28 Jun 2018, 11:42 AM
Hello Lee,

The problem with this is that the actual axis line does not have padding and margin properties available. What I can suggest as an alternative is to hide the second category axis line and move its labels down using padding:
.CategoryAxis(axis => axis
   .Labels(lbl => lbl.Visible(false))
)
.CategoryAxis(axis => axis
   .Categories(Model.Categories)
   .Line(line=>line.Visible(false))
   .Labels(lbl=>lbl.Padding(20, 0, 0, 0))
)


Regards,
Tsvetina
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Grid
Asked by
Lee
Top achievements
Rank 1
Veteran
Answers by
Tsvetina
Telerik team
Lee
Top achievements
Rank 1
Veteran
Share this question
or