Pre loader

Dynamically Updating Legend in JS

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

1
0

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

Version
3
  • You must to post comments
0
0

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

  • You must to post comments
0
0

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!

  • Andrew Burnett-Thompson
    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 to post comments
0
0

Actually, the invalidateLegend doesn’t seem to always be working, so I’m guessing I have a race condition somewhere.

  • You must to post comments
0
0

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?

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.