Charting Library and Bootstrap 5 (Specifically stacked bar)
Added by Mark Travis over 1 year ago
I'm getting close to implementing some reporting using charts and I'm curious how the Charting library interacts with other charting libraries based on Bootstrap 5.
I would like to create some stacked bar charts, but I don't specifically see that mentioned in the charting library.
Something like this would be perfect: https://think.design/services/data-visualization-data-design/stacked-bar-chart/
Replies (12)
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck over 1 year ago
Hello Mark,
I do not believe that this is currently something supported by Wt in a default implementation.
To facilitate this, you'll have to implement your own WAbstractItemModel and WAbstractItemView.
I'd probably look at using std::tuple
to store datapoints, which will then indicate each section of the bar.
As for styling, that is currently handled completely separately from the theme, it's essentially now just a WPainter to which we render axis, and bars (or something else depending on the type of chart). As such it doesn't have any style classes per item we can change, and apply a theme to.
There are a lot of configurable options to change the chart's appearance, but they will all have to be made in code (e.g. setPalette), not CSS.
I hope this is helpful,
Matthias
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis over 1 year ago
Very helpful, thank you!
I noticed in the web-browser inspect mode that none of the data points to make the charts are delivered to the browser, so that they could be picked off to hand over to a package such as chart.js. It's a very tight Wt integration.
That would be an interesting project to expose the necessary elements to incorporate something like chart.js. Maybe once revenue starts flowing and I can hire some other programmers I could look at it again.
Maybe something for Wt V5.x
Thanks!
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck over 1 year ago
I believe it was set up like this, since many years ago having JS in the browser wasn't a given. So this avoids that possibility, and essentially guarantees output and consistency.
But indeed it is far from extensible.
I know for a fact that a colleague has worked with some chart JS library before, I'll ask around to see how they approach that, and update you on it soon.
Best,
Matthias
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis over 1 year ago
Hi Matthias! Yes, I'd love to get any information about how others have implemented Chart.js. Thanks!
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck about 1 year ago
Hello Mark,
I ask around, and they indeed did a custom implementation. How the implementation work right now is that:
- they use a certain library to visualize the data (say e.g. Chart.js)
- a wrapper (in JS) around that library was written, to easily manage the library
- a widget (in C++) was created that manages this wrapper, so the widget will offer certain methods to manage the data (this is both with a model or by manually defining a serie, that option is open to you, whichever is handiest for you) and add visuals/labels
- the widget (C++) also has a
render(Wt::WFlags<Wt::RenderFlag>) override
method. This manages the set-up of the JS object (on full render) or updates to the UI otherwise), this passes the data in the expected format managed by the wrapper (JS)
I hope this gives somewhat of an idea. I will look into creating a more plug-in approach, but will have to look into some existing libraries, and see how we can generically handle those.
Best,
Matthias
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis about 1 year ago
Thanks Matthias!
I created a fork in Wt to integrate D3js. It seems to be the least complicated to implement at a basic level as it's all self-contained in one library file. (But it will probably be the most complicated to extend to all of the functionality.)
I plan to use WLeafletMap as a guide as the wrappers and widgets seem to be about as similar as I can find at this moment.
If successful, it will be my first open-source contribution. (I've always been on the product management side in the past.)
Hopefully, I can get the basics in place (including the docs), and others can help extend it over time.
Will that work?
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck about 1 year ago
That's very interesting and I look forward to seeing what you can do with it!
I am not familiar with D3js (I'm not familiar with a lot of JS generally), but it looks like a very broad library that offers a lot. So from a glance, that looks great.
It's obviously a bit early to say whether this will be a good approach, that is generic enough for Wt. But I will be certain to discuss this matter further internally.
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis 15 days ago
When building the C++ wrapper for Charts.js, it seems like WPaintedWidget would be the best candidate to inherit from since it creates the Canvas tag.
I can get the Canvas ID by prepending a "c" to the jsRef() result.
Would this create any conflicts with what WPaintedWidget was intended to do?
I would need to reimplement paintEvent(WPaintDevice *paintDevice)
instead of (or in addition to?) render(Wt::WFlags<Wt::RenderFlag>) override
.
Otherwise, it looks like I would need to create a WTemplate with a Canvas tag and inherit from WContainerWidget for the wrapper.
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck 4 days ago
Hey Mark,
you can use the c + jsRef()
ID, that ought to be be safe.
The render
function takes care of:
- loading interactivity (click / keyboard)
- loading the necessary JS
You can override this, and then load any JS file you require there, as long as you call the base again.
Then indeed, you will be required to implement paintEvent
.
Best,
Matthias
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis 4 days ago
Thanks Matthias! I'm at the point of almost having it working. I think I need to move a few things out of paintEvent and put them in render.
It looks like I need to choose between creating Wt::Json packages and then having the js wrapper unpack it with JSON.parse (like WLeafletMap) due to the quotation marks,
or use a std::map and use Wt::Impl::asJSLiteral(configVariable, Wt::TextFormat::UnsafeXHTML); (like WTextEdit)
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Mark Travis 3 days ago
And Wt::Json coupled with JSON.parse in the .js wrapper for the win!
It's not the prettiest C++ library interface, yet, but at least it uses WAbstractItemModel/WStandardItemModel to handle the data.
I don't think I need to do anything with the paintEvent() callback as Chart.js takes the Canvas identifier and does all of the drawing. About the only thing I'm doing in the paintEvent() right now is resizing to match the parent object, but I'm not sure I need to do that either as Chart.js is "responsive."
I came up with C++ objects to handle 3 of the main categories of options (data, plugins, options) using Wt::Json to assemble the "tree" structures.
I probably need to break those objects down into one more level of abstraction to get them to be "intuitive" to use. Right now, it's hard to see the forest for the trees, so to speak.
But it works!!
Now if we can just get Wt to load ES6 modules using type = "module" ....
RE: Charting Library and Bootstrap 5 (Specifically stacked bar) - Added by Matthias Van Ceulebroeck 2 days ago
Hey Mark,
happy to hear you got it working.
I hear the suggestion for a charting library loud and clear, and I honestly do think Wt can use it. A lot of the charts feel dated.
However, it's not a straightforward choice; One with a couple of side-effects (on existing code), and further implications.
What I will do with the ticket you created is schedule it to the future
target version. This means that is will be up for consideration in upcoming versions (4.13+). We'll then take a more concrete look at it, investigate how feasible it is, and decide how we move forward with it.
As for the module support, this is also a suggestion we're aware of (e.g. #6623). I will do the same for that ticket.