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

Saving a report with the ActiveReportsJS Designer

The reports 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 "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 set up onSave and onSaveAs action handlers for the designer component instance to enable 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 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 as ReportDesigner,
} from "@grapecity/activereports/reportdesigner";

export const DesignerHost: React.FC = () => {
  const designerRef = React.useRef<ReportDesigner | undefined>();
  const counter = React.useRef<number>(0);
  const [reportStorage, setReportStorage] = React.useState(new Map());

  React.useEffect(() => {
    designerRef.current = new ReportDesigner("#designer-host");
    designerRef.current.setActionHandlers({
      onSave: function (info) {
        const reportId = info.id || `report${counter.current++}`;
        setReportStorage(new Map(reportStorage.set(reportId, info.definition)));
        return Promise.resolve({displayName: reportId});
      },
      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"></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 a React application, and Angular, Vue, or pure JavaScript applications can use the same technique.

import {
  Designer as ReportDesigner,
  templates,
} from "@grapecity/activereports/reportdesigner";
import React, { Fragment } from "react";
import "@grapecity/activereports/styles/ar-js-ui.css";
import "@grapecity/activereports/styles/ar-js-designer.css";

export const DesignerHost: React.FC = () => {
  const designerRef = React.useRef<ReportDesigner | undefined>();
  React.useEffect(() => {
    designerRef.current = new ReportDesigner("#designer-host");

    // onSave and onSave handlers are defined here just as shown above

    const saveIntervalId = setInterval(async () => {
      const reportInfo = await designerRef.current?.getReport();
      if (reportInfo?.isDirty) {
        designerRef.current?.processCommand("save");
      }
    }, 2000);
    return () => clearInterval(saveIntervalId);
  }, []);
  return (
   <div id="designer-host"></div>
  );
};