1

Hi Everyone and Thanks in advance.

I have created a web application using delphi xe2 and unigui. In my application, I display charts using Highcharts for delphi(THTMLCharts) with the use of UniGui. In displaying charts, this is the original process:

  1. Organize the fields and values for display.
  2. Provide the highchart(THTMLCharts) object of the fields and values.
  3. Recreate the charts. Recreate the series and drilldown values.
  4. Redraw the charts.

That process is being executed every 10 seconds in a timer to update the charts on display. We notice that it's a bit of a process and not user friendly if the user keeps on seeing the page being refreshed every 10 seconds to update the charts. Increasing the timer's interval is not a very a good thing as the user should at least see the latest updates immediately without clicking any button for refresh. The Web application is like some sort of Dashboard that is always open and should remain on a same page while the charts are being updated.

So I searched online on how to update data of a chart in a highchart object for delphi. Please note that the delphi object for highchart does not have the option to just update values but rather requires redrawing. We found online for highchart site for the 'setData' javascript function and initially, it is working. The javascript is passed through Unisession.AddJS.

Please note in delphi unigui, the term 'frame(s)' are the web pages.

The issue here is, it only works on the initial loading of the charts, but, when the frames are reloaded, say we switch views to a different frame, then go back to the charts (which will then redraw the charts), the setData function is no longer working, both through the source code(delphi) and in the browser's console.

Would anyone have any knowledge as to why this occurs? We cannot fully refresh the page because this will just put everything back to the very first page, which is the login page.

Below is the code I'm using to compose the setData function as well as how it is passed to the display

procedure TGraphPageFrame.SetDataPass(chrt: THTMLFrameChart; nChartIndex : Integer; isDrillDown: Boolean; isNewData: Boolean = False);
var
  oSeriesOtherInfos : TSeriesOtherInfos;
  
  srsCount : integer;

  srsVal : TSeriesValues;
  drilldownVal : TItemSeriesValues;

  extn_datas: TlkJSONlist;
  extn_data: TlkJSONobject;
  extn_names : TStringList;
  
  y, z, ndx: Integer;
  nTot : Double;

  sJSCommand,
  sJSCommand_drilldown,
  sChartIndex,
  sChartDatas ,
  sDrillDownName : string;
begin
  sChartIndex := IntToStr(nChartIndex);

  extn_datas := TlkJSONlist.Create;
  extn_names := TStringList.Create;
  extn_names.OwnsObjects := True;
  
  try
    try
      srsVal := chrt.Series.Items[0].Values;
      srsCount := srsVal.count;

      for y := 0 to srsCount - 1 do
      begin
        ndx := extn_names.IndexOf(srsVal.Items[y].Title);

        sDrillDownName := 'DrillDown_'+ srsval.Items[y].Title;

        if ndx < 0 then
        begin
          extn_data := TlkJSONobject.Create;
          extn_data.Add('name', srsVal.Items[y].Title);

          oSeriesOtherInfos := TSeriesOtherInfos.Create;
          oSeriesOtherInfos.nIndex := extn_names.Count;

          extn_names.AddObject(srsVal.Items[y].Title, oSeriesOtherInfos);
        end
        else
        begin
          oSeriesOtherInfos := TSeriesOtherInfos(extn_names.Objects[ndx]);

          extn_data := TlkJSONobject(extn_datas.Child[oSeriesOtherInfos.nIndex]);
        end;
    

        nTot := 0;
        if isDrillDown then
        begin
          for z := 0 to srsVal.Items[y].drilldown.Items[0].Values.Count - 1 do
          begin
            drilldownVal := srsval.Items[y].drilldown.Items[0].Values.Items[z];
            nTot := nTot + drilldownVal.Value;
          end;
        end
        else
        begin
          nTot := srsVal.Items[y].Value;
        end;

        if ndx < 0 then
        begin
          extn_data.Add('y', nTot);
          if isDrillDown then
            extn_data.Add('drilldown', sDrillDownName);
          extn_datas.Add(extn_data);
        end
        else
        begin
          extn_data.Field['y'].Value := nTot;
        end;
      end;

      sChartDatas := TlkJSON.GenerateText(extn_datas);
      sChartDatas := StringReplace(sChartDatas, '"name"', 'name', [rfReplaceAll]);
      sChartDatas := StringReplace(sChartDatas, '"y"', 'y', [rfReplaceAll]);
      sChartDatas := StringReplace(sChartDatas, '"drilldown"', 'drilldown', [rfReplaceAll]);

      sJSCommand := 'Highcharts.charts['+ sChartIndex +'].series[0].setData('+sChartDatas+', false, true, true);';

      UniSession.AddJS(sJSCommand);

      if isDrillDown then
      begin
        sleep(500);

        UniSession.AddJS('Highcharts.charts['+ sChartIndex +'].options.drilldown.series.length = 0;');

        Sleep(500);

        srsCount := srsVal.count;

        for y := 0 to srsCount - 1 do
        begin
          sDrillDownName := '"DrillDown_'+ srsval.Items[y].Title +'"';

          sJSCommand_drilldown := 'Highcharts.charts['+ sChartIndex +'].options.drilldown.series.push('+
            '{'+
              'type: "bar",'+
              'name: "'+ srsval.Items[y].Title +'",'+
              'color: "#ef6986",'+
              'id: ' + sDrillDownName + ',' +
              'showInLegend: true,'+
              'dataLabels:{enabled: true, format: "{point.y}"},'+
              'tooltip:{animation: true, enabled: true, hideDelay: 500, pointFormat: "{point.y}"},'+
              'data:[';

          for z := 0 to srsVal.Items[y].drilldown.Items[0].Values.Count - 1 do
          begin
            drilldownVal := srsval.Items[y].drilldown.Items[0].Values.Items[z];

            sJSCommand_drilldown := sJSCommand_drilldown +
              '["'+ drilldownVal.Title +'",'+ FloatToStr(drilldownVal.Value) +'],';
          end;         

          sJSCommand_drilldown := Copy(sJSCommand_drilldown, 1, Length(sJSCommand_drilldown) - 1);
          sJSCommand_drilldown := sJSCommand_drilldown +
            ']' + '}' + ');';
          
          UniSession.AddJS(sJSCommand_drilldown);

          Sleep(100);
        end;
      end;
    except
      on E:Exception do
      begin
        ShowMessage('SetDataPass::Exception = ' + e.Message);
      end;
    end;
  finally
    FreeAndNil(extn_names);
    FreeAndNil(extn_datas);
  end;
end;
  • I don't know the delphi-xe2 at all and `THTMLCharts`, but from the Highcharts view you can try to set the setData event inside the load callback which triggers after each chart rendering (includes switching the pages) - https://api.highcharts.com/highcharts/chart.events.load – Sebastian Wędzel Apr 02 '21 at 09:06

0 Answers0