Wants to Download the row data in .json format on click of a cell

Posted by: ratnesh on 16 April 2025, 3:17 am EST

  • Posted 16 April 2025, 3:17 am EST - Updated 16 April 2025, 3:23 am EST

    I tried to use a column Named Errors and put Action Type Jump to a url in that column property and i provided a url in that case, but what i actually want is if i can have a link click event or cell clicked event then i will be able to make the row data downloadable,

    my whole idea is user should be able to download individual row data in json format file.

    export class PublishRoutesComponent implements OnInit {
      updateSourceReportTemplate: Core.Rdl.Report = report;
      accountID: number | undefined;
      routeType: string | undefined;
      opsUnit: string | undefined;
      startDate: string | undefined;
      endDate: string | undefined;
      public availableExports: string[] = availableExports; //ZRP-1658 use for the Rename the file before export
    
      @ViewChild(ViewerComponent, { static: false }) ref: ViewerComponent = new ViewerComponent();
      reportViewer: ReportViewer.Viewer | undefined;
      exportsSettings: Record<string, ReportViewer.ExportSettings> = {
        pdf: {
          title: 'Zignex-Report',
          author: 'Zignex',
          subject: 'Update Source Report',
          pdfVersion: '1.7',
          autoPrint: false,
          filename: 'Update-Source-Report-' + timeStamp
        },
        xlsx: {
          creator: 'Zignex',
          size: 'Letter',
          orientation: 'Landscape',
          sheetName: 'Page',
          MultiSheet: false,
          filename: 'Update-Source-Report-' + timeStamp
        },
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'tabular-data': {
          outputType: 'plain',
          filename: 'Update-Source-Report-' + timeStamp
          // default value for other TabularData export settings
        }
      };
      constructor(
        public spinner: SpinnerService,
        private _route: ActivatedRoute,
        private _http: HttpService,
        private _toast: HotToastService
      ) {}
    
      ngOnInit(): void {
        this._route.queryParams.subscribe((params: IZPRRRouteParams) => {
          this.accountID = params['accountID'];
          this.routeType = params['routeType'];
          this.opsUnit = params['opsUnit'];
          this.startDate = params['fromDate'];
          this.endDate = params['toDate'];
        });
        this._http.setTitle(`Update Source`);
      }
    
      /**
       * Initializes the report viewer and fetches report data based on provided parameters.
       *
       * This method performs the following steps:
       * 1. Assigns the report viewer reference.
       * 2. Checks if all required parameters (`accountID`, `opsUnit`, `routeType`, `startDate`, `endDate`) are present.
       *    - If parameters are valid:
       *      - Sends an HTTP GET request (`publishRoutesReport`) to fetch the report data.
       *      - Formats the `published_dtm` and `creation_dtm` fields for each data entry.
       *      - Updates the report template with the fetched data.
       *      - Configures and renders the report viewer.
       *    - If parameters are missing:
       *      - Clears the report template connection string.
       *      - Displays an error toast notification.
       *
       * @returns {Promise<void>}
       */
      async onViewerInit(): Promise<void> {
        this.reportViewer = this.ref.ref;
        if (this.accountID && this.opsUnit && this.routeType && this.startDate && this.endDate) {
          const params: (string | number)[] = [this.accountID, this.opsUnit, this.routeType, this.startDate, this.endDate];
          this._http
            .getRequest<IZPublishRoutesData[], null, { responseType: 'json' }>('publishRoutesReport', {
              responseType: { responseType: 'json' },
              requestParams: params
            })
            .subscribe({
              next: (data: IZPublishRoutesData[]) => {
                // data = sampleUpdateSource;
                console.log('Publish Routes Report Data:', data);
                sampleUpdateSource.map((e: IZPublishRoutesData) => {
                  e.linkName = '';
                  if (e.errors && toUpper(e.trans_st) === 'FAILED') {
                    e.url = this.downloadErrorJson(e);
                    e.linkName = 'View Error';
                  }
                  if (e.trans_st === 'Success') {
                    e.textColor = '#008000'; //Success green color
                  } else {
                    e.textColor = '#FF0000'; //Failed Red color
                  }
                  e.published_dtm = formatDate(new Date(e.published_dtm), 'yyyy-MM-dd HH:mm:ss', 'en-us');
                  e.creation_dtm = formatDate(new Date(e.creation_dtm), 'yyyy-MM-dd HH:mm:ss', 'en-us');
                  return e;
                });
                this.spinner.removeSpinner();
                if (this.updateSourceReportTemplate?.DataSources) {
                  const routeDetailReportTemplate0: DataSource | undefined = this.updateSourceReportTemplate.DataSources[0];
                  if (routeDetailReportTemplate0?.ConnectionProperties)
                    routeDetailReportTemplate0.ConnectionProperties.ConnectString =
                      'jsondata=' + JSON.stringify(sampleUpdateSource);
                } else {
                  // Handle the case where updateSourceReportTemplate is a string or undefined
                  console.error('updateSourceReportTemplate is not a valid report template');
                }
                if (this.reportViewer) {
                  this.reportViewer.renderMode = 'Paginated';
                  this.reportViewer.viewMode = 'SinglePage';
                  this.reportViewer.zoom = 'FitToWidth';
                  this.reportViewer.toolbar.updateLayout({
                    default: [
                      '$openDesigner',
                      '$split',
                      '$navigation',
                      '$split',
                      '$refresh',
                      '$split',
                      '$history',
                      '$split',
                      '$zoom',
                      '$fullscreen',
                      '$split',
                      '$print',
                      '$split'
                      // "$galleymode",
                    ]
                  });
                  if (this.updateSourceReportTemplate)
                    this.reportViewer.open(this.updateSourceReportTemplate).catch((err: Error) => {
                      console.error(err);
                    });
                }
              },
              error: (error: Error) => {
                console.error(error);
                this.spinner.removeSpinner();
              }
            });
        } else {
          if (this.updateSourceReportTemplate?.DataSources) {
            const routeDetailReportTemplate0: DataSource | undefined = this.updateSourceReportTemplate.DataSources[0];
            if (routeDetailReportTemplate0?.ConnectionProperties)
              routeDetailReportTemplate0.ConnectionProperties.ConnectString = '';
          }
          this._toast.error(this._http.reqParamsError);
        }
      }
      downloadErrorJson(errorData: IZPublishRoutesData): string {
        const blob: Blob = new Blob([JSON.stringify(errorData, null, 2)], {
          type: 'application/json'
        });
    
        return URL.createObjectURL(blob);
        // const url: string = URL.createObjectURL(blob);
        // const a: HTMLAnchorElement = document.createElement('a');
    
        // a.href = url;
        // a.download = `${fileName}.json`;
        // document.body.appendChild(a);
        // a.click();
    
        // // Cleanup
        // document.body.removeChild(a);
        // URL.revokeObjectURL(url);
      }
    }

    in this you might can see that for download i will require a click event or somehow i can add html to the rows, or else so that i can download it

    Please provide me any solution what i can do in that case

  • Posted 17 April 2025, 5:13 am EST

    Hi,

    Here’s a sample implementation on how you can do it. Note, in the sample I added an API which only accepts product ID as a query parameter and uses it to fetch the row details from the DataBase. You may modify the URL and the API as per your use case.

    ViewerRowLink.zip

  • Posted 17 April 2025, 6:34 am EST

    Hey,

    thank you for your response,

    I am using Active Reports JS instead of .net, so can you please provide the solution in that

  • Posted 23 April 2025, 5:09 am EST

    Hi Ratnesh,

    The hyperlink function only allows you to open URL. For ActiveReportsJS as well you would need an API which must be called with the required information(in say Query parameters) to get the information of the Row and download a JSON file.

    So from the ActiveReportsJS perspective you may add the URL to the API which returns a JSON file.

    If you want to add custom click events, then after the report is loaded, I would suggest adding a click handler on the Viewer component and and stop click propagation and prevent default. Sample Code:

    component.ts

    onViewerClick(e: any) {
        const target = e.target as HTMLElement;
      
        // Try to find the span.arjs-action[data-action], either as the target or inside it
        let actionSpan: HTMLElement | null = null;
    
        if (
          target.tagName.toLowerCase() === 'span' &&
          target.classList.contains('arjs-action') &&
          target.hasAttribute('data-action')
        ) {
          // Directly clicked the span
          actionSpan = target;
        } else if (
          target.tagName.toLowerCase() === 'div' &&
          target.classList.contains('arjs-textBoxContent')
        ) {
          const directChild = target.querySelector(':scope > span.arjs-action[data-action]');
          if (directChild) {
            actionSpan = directChild as HTMLElement;
          }
        }
      
        if (actionSpan) {
          e.stopPropagation();
        e.preventDefault();
          const dataAction = actionSpan.getAttribute('data-action');
          console.log('data-action:', dataAction);
      
          // Example if you want to parse the JSON
          try {
            const parsedAction = JSON.parse(dataAction!);
            console.log('Parsed Action:', parsedAction);
          } catch (err) {
            console.error('Invalid JSON in data-action:', dataAction);
          }
      
          // You can do more stuff here with `parsedAction`
          return;
        }
      }
    
    

    component.html:

    <div id="viewer-host" (click)="onViewerClick($event)">
        <gc-activereports-viewer (init)="onViewerInit()"></gc-activereports-viewer>
      </div>
    
Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels