Megabit / Blazorise

Blazorise is a component library built on top of Blazor with support for CSS frameworks like Bootstrap, Tailwind, Bulma, AntDesign, and Material.
https://blazorise.com/
Other
3.26k stars 526 forks source link

Setting Chart Options #297

Closed andrewwilkin closed 4 years ago

andrewwilkin commented 4 years ago

Have been reading through the source code and looking at demo but cannot seem to find out how to set the options in a way that works. Using a Bar Chart not that I think it makes a difference.

In HandleRedraw I've tried:

Neither seem to have an impact, as still get the Axis, Tooltip, and Legend.

            barChart.AddDataSet(GetBarChartDataset());

            var options = new BarChartOptions();
            options.Tooltips.Enabled = false;
            options.Scales.XAxes[0].Display = false;
            options.Scales.YAxes[0].Display = false;
            options.Legend.Display = false;

            barChart.SetOptions(options);

Any pointers appreciated :)

andrewwilkin commented 4 years ago

Sort of getting there, wondering though if there is an easier way of doing this though:

            var options = new BarChartOptions();

            if (options.Tooltips == null)
                options.Tooltips = new Tooltips();
            options.Tooltips.Enabled = false;

            if (options.Legend == null)
                options.Legend = new Legend();

            options.Legend.Display = false;

            if (options.Scales == null)
                options.Scales = new Scales();

            if (options.Scales.XAxes == null)
                options.Scales.XAxes = new List<Axe>();

            if (options.Scales.XAxes.Count == 0)
                options.Scales.XAxes.Add(new Axe());

            options.Scales.XAxes[0].Display = false;
            options.Scales.XAxes[0].GridLines = new AxeGridLines();
            options.Scales.XAxes[0].GridLines.Display = false;
            options.Scales.XAxes[0].Ticks = new AxeTicks();
            options.Scales.XAxes[0].Ticks.Display = false;
            options.Scales.XAxes[0].Ticks.Minor = new AxeMinorTick();
            options.Scales.XAxes[0].Ticks.Major = new AxeMajorTick();

            if (options.Scales.YAxes == null)
                options.Scales.YAxes = new List<Axe>();

            if (options.Scales.YAxes.Count == 0)
                options.Scales.YAxes.Add(new Axe());

            options.Scales.YAxes[0].Display = false;
            options.Scales.YAxes[0].GridLines = new AxeGridLines();
            options.Scales.YAxes[0].GridLines.Display = false;
            options.Scales.YAxes[0].Ticks = new AxeTicks();
            options.Scales.YAxes[0].Ticks.Display = false;
            options.Scales.YAxes[0].Ticks.Minor = new AxeMinorTick();
            options.Scales.YAxes[0].Ticks.Major = new AxeMajorTick();

            barChart.SetOptions(options);

            await barChart.Update();

Would be nice to have these initialized by default and some helpers. Thoughts?

stsrki commented 4 years ago

I would like to recommend you the Options attribute for charts but unfortunately the JSON serializer that comes with .NET Core and Blazor is just bad. I'm waiting almost a year now for JSON serializer to be fixed and so far nothing has changed. Instead they introduced System.Text.Json that is even more buggy.

So instead of Options attribute I recommend you to use OptionsJsonString instead. I know it's not the easiest way but for now it's the best.

PS. You now gave me an idea. Maybe I could implement fluent-builder for chart that could be used to define options. I will need to think this through 🤔

andrewwilkin commented 4 years ago

On a side note, for some reason I am only seeing the first bar in the bar chart and for the life of me I cannot see what I am doing wrong having looked through your example in ChartsPage.razor.

Adding multiple datasets works just fine but that's not quite the same and may want to use that elsewhere.

P.s. Thanks for the quick response, and get your frustration about the serializer

stsrki commented 4 years ago

Yeah, it's just a shame because u a lot of people is having issue with JSON and it everything just goes too slow.

Can you post a sample code so I can have a look?

andrewwilkin commented 4 years ago

Fixed it but didn't think it would have an impact...

If you don't add labels to the chart it only shows the first in the data set. Is that expected behaviour?

stsrki commented 4 years ago

Could be. Blazorise is using charts.js so maybe that's the way how it works.

andrewwilkin commented 4 years ago

Have tried to send hard coded options to a chart using the JSON method, but it fails to deserialize. Have tried multiple ways of hand crafting this such as:

        private string GetChartOptions()
        {
            var jsonSB = new StringBuilder();

            jsonSB.Append(@"{ ");
            jsonSB.Append(@"'scales': ");
            jsonSB.Append(@"{ ");
            jsonSB.Append(@"'yAxes': [{ ");
            jsonSB.Append(@"'ticks': ");
            jsonSB.Append(@"{ ");
            jsonSB.Append(@"'min': 0, ");
            jsonSB.Append(@"'max': 50000 ");
            jsonSB.Append(@"} ");
            jsonSB.Append(@"}] ");
            jsonSB.Append(@"} ");

            Console.WriteLine(jsonSB.ToString());
            return jsonSB.ToString();
        }

Cannot seem to get it working, double quotes etc. Any pointers?

andrewwilkin commented 4 years ago

WASM: { 'scales': { 'yAxes': [{ 'ticks': { 'min': 0, 'max': 50000 } }] } blazor.webassembly.js:1 WASM: Unhandled exception rendering component: d.printErr @ blazor.webassembly.js:1 blazor.webassembly.js:1 WASM: Microsoft.JSInterop.JSException: Unexpected token ' in JSON at position 2 d.printErr @ blazor.webassembly.js:1 blazor.webassembly.js:1 WASM: SyntaxError: Unexpected token ' in JSON at position 2

stsrki commented 4 years ago

Keys should definitely need to be in double quotes. Other then that I don't see any other issues. Maybe also add quotes to min and max values but I think that's not necessary.

{ "scales": { "yAxes": [{ "ticks": { "min": 0, "max": 50000 } }] }

andrewwilkin commented 4 years ago

Sweet double quotes worked. Given all the other options that are a pain to expose until the JSON serializer is fixed this is definitely the way to go. Building something to wrap the options and then the dataset where necessary.

Thanks for your help :)

andrewwilkin commented 4 years ago

@stsrki been thinking (I know dangerous right). So I've tried this...

        async Task HandleRedraw()
        {
            lineChart.Clear();

            lineChart.AddLabel(Labels);

            lineChart.AddDataSet(GetLineChartDataset());

            dynamic chartOptions = new ExpandoObject();
            dynamic title = new ExpandoObject();
            chartOptions.title = new ExpandoObject() as dynamic;
            chartOptions.title.display = true;
            chartOptions.title.text = "Chart Title Dynamic";

            lineChart.OptionsJsonString = JsonConvert.SerializeObject(chartOptions, new ExpandoObjectConverter());

            await lineChart.Update();
        }

Requires using JSON.net, and a reference to CSharp NuGet package. If that were acceptable to users of the package it would make it possible to build a fluent config builder.

stsrki commented 4 years ago

I've being thinking about that already but I don't want to introduce third-party packages to Blazorise core as it could lead to versioning hell. Also json strings can be used as a workaround for now, at least until the serializer is fixed. Unfortunately I think we will have to wait for .NET 5 according to the aspnetcore milestone..

NGE2015 commented 4 years ago

andrewwilkin, i was reading your comments, I was trying to understand at least 20% but still hard. So my question is : I would like to activate the values visible on chart ( right now is only tooltip ) . Blazorise have that option ? And if yes, how do activate ?

andrewwilkin commented 4 years ago

@NGE2015 am focused on other things right now but hopefully this will point you in the right direction. Out the box this is not possible with ChartJS, but there is a plugin for displaying values.

You would need to work out how to setup the config for it.