v2.1.0
v2.1.0v2.0.0v1.2.0

Saving a report with the ActiveReportsJS Designer

The report's storage type and the exact manner to save a report displayed in the ActiveReportsJS designer's instance depend on the application's architecture. This page provides recipes for several common scenarios.

Enabling the "Save" and "Save As" buttons

The ActiveReportsJS Report Designer component contains the "Save" and "Save As" buttons on the toolbar.

ARJS Designer

They are not enabled and not visible by default, however. The code should configure onSave and onSaveAs action handlers for the designer component to allow these buttons. Check Action Handlers page for more information. The onSaveAs handler should return the Promise that resolves to the object containing the id and the optional displayName properties of the report - the former uniquely identifies the report, the latter displays on the top bar of the designer component. The onSave handler should return the Promise that resolves to the object containing the optional displayName property of the report. Here is the example of the onSave and onSaveAs handlers that save reports in the React application's in-memory storage. You can use a similar approach to save reports by sending requests to the REST API because these handlers are async functions that return the Promise object.

import React, { Fragment } from "react";
import { Designer } from "@grapecity/activereports-react";

function App() {
  const counter = React.useRef(0);
  const [reportStorage, setReportStorage] = React.useState(new Map());

  const onSave = function (info) {
    const reportId = info.id || `report${counter.current++}`;
    setReportStorage(new Map(reportStorage.set(reportId, info.definition)));
    return Promise.resolve({ displayName: reportId });
  };

  const onSaveAs = function (info) {
    const reportId = info.id || `report${counter.current++}`;
    setReportStorage(new Map(reportStorage.set(reportId, info.definition)));
    return Promise.resolve({ id: reportId, displayName: reportId });
  };

  return (
    <div id="designer-host">
      <Designer onSave={onSave} onSaveAs={onSaveAs} />
    </div>
  );
}

Visit the Live Demo for the complete examples for React, Angular, Vue, and pure JavaScript applications.

Autosave

The processCommand method of the ActiveReportsJS Report Designer component's instance accepts one of the save, saveAs, create, open, and render arguments and invokes the corresponding action handler. Check Action Handlers page for more information. The getReport method of the designer component returns the current report's info, including the isDirty flag that indicates whether the report changed since the last save. It is possible to implement autosave functionality by using these two methods together. Here is the example of this approach for an Angular application, and React, Vue, or pure JavaScript applications can use the same technique.

import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { DesignerComponent } from '@grapecity/activereports-angular';

@Component({
  selector: 'app-root',
  template:
    '<div id="designer-host"><gc-activereports-designer [onSave]="onSave" [onSaveAs]="onSaveAs" > </gc-activereports-designer></div>',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit, OnDestroy {
  saveIntervalId = null;
  @ViewChild(DesignerComponent, { static: false })
  reportDesigner: DesignerComponent;

  onSave = function (info) {
    // the implementation of the onSave handler
  };
  onSaveAs = function (info) {
    // the implementation of the onSaveAs handler
  };

  ngAfterViewInit(): void {
    this.saveIntervalId = setInterval(async () => {
      const reportInfo = await this.reportDesigner.getReport();
      if (reportInfo?.isDirty) {
        this.reportDesigner.processCommand('save');
      }
    }, 2000);
  }
  ngOnDestroy(): void {
    clearInterval(this.saveIntervalId);
  }
}