Hi there,
Wow this library has come along way in ten years. My question is related to interaction between RS and the legend that is rendered by the chartmodifier.
I declare the legend something like this during the initial bootstrapping of the plot view:
const legend = new LegendModifier({placementDivId: "legend-goes-here", id:"legend"});
sciChartSurface.chartModifiers.add(legend);
After that, I have a custom interface available for users to change things, which eventually results in visibility or color changes, updating an RS something like this:
const thisRs = surface.renderableSeries.getById(`${s.fileId}-${s.name}`);
if (thisRs) {
thisRs.isVisible = s.isVisible;
thisRs.stroke = s.visualInfo?.colorCode ?? "#FFFFFF";
}
These changes do not appear to be propagated to the legend despite the series on the plot changing. I guess my questions are:
1) What’s the expected behavior/is there something obvious I’m missing about the model?
2) Any suggestions?
It may very well be somewhere lost in my fairly complex React app, but I first wanted to confirm that I’m not missing something in the api.
Thanks!
Dan
- Daniel Santimore asked 11 months ago
- last edited 11 months ago
- You must login to post comments
Hi Dan,
This should ‘just work’ out of the box. The quickest way to test this is with a codepen.
Here, I took an example from our documentation – Series isVisible and isVisibleChanged API. Most of our docs now have working code samples embedded in them using Codepen. This page above shows how to subscribe to isVisibleChanged events. The checkbox in the legend should bind & propagate to series.isVisible. Let’s see if it works in the other direction.
Codepen: Legend Checkbox bi-directional binding
OK so interestingly checking the legend checkbox sets series.isVisible. But setting series.isVisible in code does not toggle the legend checkbox.
Unless .. you do this:
scatterSeries.isVisible = !scatterSeries.isVisible;
// Doesnt work without this line
legendModifier.sciChartLegend?.invalidateLegend();
Note you can also do this
const hackUpdateLegend = (series) => {
series.parentSurface?.chartModifiers?.asArray()?.find(cm => cm.type === EChart2DModifierType.Legend)?.sciChartLegend?.invalidateLegend();
};
document.getElementById("button").addEventListener("click", () => {
scatterSeries.isVisible = !scatterSeries.isVisible;
// Doesnt work without this line
hackUpdateLegend(scatterSeries);
});
I think this should work bi-directionally but we will have to consider how best to do it, as we don’t want event listeners all over the place which can stop objects from getting garbage-collected.
Here’s the full code sample.
async function testIsVisibleOnChart(divElementId) {
// Demonstrates how to listen to isVisible changes in SciChart.js
const {
SciChartSurface,
NumericAxis,
XyScatterRenderableSeries,
EllipsePointMarker,
XyDataSeries,
SciChartJsNavyTheme,
LegendModifier,
TextAnnotation,
ECoordinateMode,
EHorizontalAnchorPoint,
EVerticalAnchorPoint
} = SciChart;
// or, for npm, import { SciChartSurface, ... } from "scichart"
const { wasmContext, sciChartSurface } = await SciChartSurface.create(divElementId, {
theme: new SciChartJsNavyTheme()
});
sciChartSurface.xAxes.add(new NumericAxis(wasmContext));
sciChartSurface.yAxes.add(new NumericAxis(wasmContext));
// Add instructions
const textAnnotation = new TextAnnotation({ x1: 0.5, y1: 0.5, text: "Click on the legend to show/hide the series", textColor: "White", fontSize: 20,
xCoordinateMode: ECoordinateMode.Relative, yCoordinateMode: ECoordinateMode.Relative,
horizontalAnchorPoint: EHorizontalAnchorPoint.Center, verticalAnchorPoint: EVerticalAnchorPoint.Center})
sciChartSurface.annotations.add(textAnnotation);
// Create some data
const xValues = [];
const yValues = [];
for(let i = 0; i < 100; i++) {
xValues.push(i);
yValues.push(0.2 * Math.sin(i*0.1) - Math.cos(i * 0.01));
}
// #region ExampleA
// Create and add a series with onIsVisibleChanged handler
const scatterSeries = new XyScatterRenderableSeries(wasmContext, {
dataSeries: new XyDataSeries(wasmContext, { xValues, yValues, dataSeriesName: "Scatter Series"}),
pointMarker: new EllipsePointMarker(wasmContext, {
width: 7,
height: 7,
strokeThickness: 2,
fill: "steelblue",
stroke: "LightSteelBlue",
}),
onIsVisibleChanged: (sourceSeries, isVisible) => {
console.log(`Series ${sourceSeries.type} was set to isVisible=${isVisible}`);
}
});
// You can also subscribe to isVisibleChanged like this
scatterSeries.isVisibleChanged.subscribe((seriesVisibleChangedArgs) => {
// See SeriesVisibleChangedArgs in typedoc
const renderableSeries = seriesVisibleChangedArgs.sourceSeries;
const isVisible = seriesVisibleChangedArgs.isVisible;
console.log(`isVisibleChanged handler: Series ${renderableSeries.type} was set to isVisible=${isVisible}`);
textAnnotation.text = `${renderableSeries.dataSeries.dataSeriesName} is ${isVisible ? 'visible' : 'hidden'}`;
});
// Explicitly set visibility like this
scatterSeries.isVisible = true;
sciChartSurface.renderableSeries.add(scatterSeries);
// #endregion
// add a legend which allows showing/hiding series
const legendModifier = new LegendModifier({ showCheckboxes: true, showLegend: true });
sciChartSurface.chartModifiers.add(legendModifier);
document.getElementById("button").addEventListener("click", () => {
scatterSeries.isVisible = !scatterSeries.isVisible;
// Doesnt work without this line
legendModifier.sciChartLegend?.invalidateLegend();
});
};
Try it out?
Wow this library has come along way in ten years.
Yes it has! Thanks for the comment. Please make sure you spread the word!
Best regards,
Andrew
- Andrew Burnett-Thompson answered 11 months ago
- last edited 11 months ago
- You must login to post comments
Thanks Andrew!
I’m amazed you’re still answering the forums yourself.
I have no idea where the source of this problem is, but it does seem that if I force a re-render of the legend (e.g., display: none –> display: unset) I can get it to work. I assume that’s essentially what invalidateLegend() is doing. Using invalidateLegend()
I’m able to make it all “feel right” so I’ll go with that for now.
Thanks again!
- Daniel Santimore answered 11 months ago
- last edited 10 months ago
-
Hi Dan, did you get this resolved? Same question has come up again in a tech-support ticket. re: ‘answering forums myself’ – you have to keep your finger on the pulse of users/feedback if you want to make a good product!
- You must login to post comments
Actually, the invalidateLegend doesn’t seem to always be working, so I’m guessing I have a race condition somewhere.
- Daniel Santimore answered 10 months ago
- last edited 10 months ago
- You must login to post comments
I am considering applying server-side licensing for my javerScript application.
In the document below, there is a phrase “Our server-side licensing component is written in C++.”
(https://support.scichart.com/index.php?/Knowledgebase/Article/View/17256/42/)
However, there is only asp.net sample code on the provided github.
(https://github.com/ABTSoftware/SciChart.JS.Examples/tree/master/Sandbox/demo-dotnet-server-licensing)
I wonder if there is a sample code implemented in C++ for server-side licensing.
Can you provide c++ sample code?
Also, are there any examples to run on Ubuntu?
- Daniel Santimore answered 10 months ago
- last edited 10 months ago
- You must login to post comments
Please login first to submit.