How to add your own component to FastReport Online Designer

2026-11-10

How to add your own component to FastReport Online Designer

FastReport Online Designer lets you add your own report components — with their own icon in the palette, properties in the Properties panel and their own settings dialog. No magic involved: you write a JavaScript plugin, upload it to the builder, and it gets compiled right into the designer build.

In this article we will create a component called «Rating» from scratch, which displays a value as stars, and go the whole way: from downloading the SDK to a ready-made designer build with the plugin and the server-side part.

 


 

How a custom component is structured

The component has two halves:

  • JS plugin handles editing in the browser: the preview on the page, properties in the panel, the settings dialog and saving to .frx.
  • .NET class runs on your server and is responsible for building the report and its preview.

What ties them together is the type name: the short name of the .NET class, the type field in the plugin and the XML tag in .frx must all be one and the same string.

The two halves can be done one after another. The designer does not need the .NET class, so first we will build and test the plugin, and add the server-side part at the end.

 


 

Step 1. Download the SDK and prepare the plugin folder

In the builder, open Build → Custom components and click Download SDK. The archive contains README.md with a brief introduction and examples/DemoChartObject — a working example.

The plugin folder also serves as a working folder for your IDE. Copy examples/DemoChartObject and rename the copy to RatingObject: it already has everything ready for autocompletion — sdk.d.ts with SDK types, jsconfig.json and package.json with React types matching the React version of the designer. Run npm install in this folder and open it in your IDE.

 

Step 2. Describe the component

A plugin — a folder with the file index.jsx (or index.js). Replace the contents of RatingObject/index.jsx with the component description:

import React from 'react';
import {registerComponent, tr} from 'sdk';
import {Input, ColorInput, Button, FormField} from 'sdk/controls';

registerComponent({
  apiVersion: 1,
  type: 'RatingObject',
  core: 'net',

  palette: {
    title: 'Rating',
    info: 'Star rating',
    icon: 'icon-chart',
  },

  defaultValues: {
    'Value': 3,
    'Maximum': 5,
    'StarColor': '#f5a623',
  },

  size: {width: 160, height: 32},

  properties: [
    {prop: 'Data:Value', type: 'number', label: 'Value', attrs: {min: 0}},
    {prop: 'Data:Maximum', type: 'number', label: 'Maximum', attrs: {min: 1}},
    {prop: 'Appearance:StarColor', type: 'color', label: 'Star color'},
  ],
});

This is already enough for the component to appear in the palette and get its properties:

  • palette sets the card in the palette. The icon here is the standard one, but you can also specify your own SVG or PNG as a data:-URI.
  • defaultValues stores the default values. Only values that differ from them end up in .frx — FastReport .NET works the same way.FastReport .NET.
  • properties describes the fields of the properties panel in the format Category:Name. Fields Design:Name and Layout:Left/Top/Width/Height are added by the SDK itself.

There is no need to save and read .frx manually: the inherited implementation already knows how to work with all declared properties.

 

Step 3. Draw the preview

To make the component look like a rating on the page, add the draw method to the description. The frame, moving and resizing are provided to the component by the base class Component, so draw is only responsible for the content. Drawing must be done into the this.$content container: by the time it is called, it has already been created.

draw: function () {
  if (!this.$stars) {
    this.$stars = document.createElementNS('http://www.w3.org/2000/svg', 'g');
    this.$content.append(this.$stars);
  }

  const maximum = Number(this.prop('Maximum')) || 1;
  const value = Number(this.prop('Value')) || 0;
  const color = String(this.prop('StarColor'));
  const height = this.prop('Height');
  const step = this.prop('Width') / maximum;
  const stars = [];

  for (let i = 0; i < maximum; i++) {
    const fill = i < value ? color : '#d9d9d9';
    stars.push(`<text x="${step * (i + 0.5)}" y="${height * 0.75}" text-anchor="middle" font-size="${height * 0.8}" fill="${fill}">★</text>`);
  }

  this.$stars.innerHTML = stars.join('');
},

 

Step 4. Add the settings dialog

The settings dialog opens with a double click on the component. We will assemble it from the standard controls of sdk/controls, so that it looks like the built-in editors:

function RatingDialog ({component, popup}) {
  const ok = () => {
    component.model.submit();
    popup.submitAndClose();
    component.render();
  };

  const cancel = () => {
    component.model.clear();
    popup.close();
  };

  return (
    <div>
      <FormField label={`${tr('Value')}:`}>
        <Input half type="number" min={0} model={component.model} prop="Value"/>
      </FormField>
      <FormField label={`${tr('Maximum')}:`}>
        <Input half type="number" min={1} model={component.model} prop="Maximum"/>
      </FormField>
      <FormField label={`${tr('Star color')}:`}>
        <ColorInput half model={component.model} prop="StarColor"/>
      </FormField>
      <div style={{textAlign: 'right'}}>
        <Button variant="primary" text="OK" minWidth={60} style={{marginRight: 6}} onClick={ok}/>
        <Button minWidth={60} text={tr('Cancel')} onClick={cancel}/>
      </div>
    </div>
  );
}

The controls write changes to component.model. It is a draft: the actual properties of the component are changed only after submit(), so the Cancel button does not break anything.

Connect the dialog in the component description:

editor: (component, popup) => <RatingDialog component={component} popup={popup}/>,

 

Step 5. Translate the strings

The plugin must contain its own translations. It is convenient to use the English text as the key: if there is no translation, the designer will show the key itself.

const TRANSLATIONS = {
  en: {'Rating': 'Rating', 'Star rating': 'Star rating', 'Value': 'Value', 'Maximum': 'Maximum', 'Star color': 'Star color', 'Cancel': 'Cancel'},
  de: {'Rating': 'Bewertung', 'Star rating': 'Bewertung in Sternen', 'Value': 'Wert', 'Maximum': 'Maximum', 'Star color': 'Sternfarbe', 'Cancel': 'Abbrechen'},
};

Add the string translations: TRANSLATIONS to the component description. The designer will translate the captions in the palette and the properties panel by itself, and in your own code use tr('Value').

 

Step 6. Upload the plugin and build the designer

  1. Pack the plugin folder itself, not its contents, into the archive: the archive must contain a single root folder RatingObject. There is no need to delete node_modules before packing — the builder will take into account only the packages from dependencies, while devDependencies (including the React types) will not get into the build.
  2. On the page Build → Custom components click Upload plugin. The archive is checked immediately: if something is wrong, you will see a list of problems. The previous version of the plugin will remain in place.
  3. The plugin will appear in the list already checked. Start the build and download the designer.

Open the designer: Rating has appeared in the palette. Add it to the page, change the value in the properties panel and open the settings dialog with a double click.

If you build the designer via the Builder API, upload the archive with a POST /builderAPI/extensions request and list the plugins in the build request: "extensions": ["RatingObject"].

 

Step 7. Add the server-side part

For the server to be able to build a report with the new object, a .NET class with the same name in a separate assembly is required:

public class RatingObject : ReportComponentBase
{
    // Draw, Serialize, Deserialize, Assign
}

public class RatingAssemblyInitializer : AssemblyInitializerBase
{
    public RatingAssemblyInitializer()
    {
        RegisteredObjects.Add(typeof(RatingObject), "ReportPage", myBitmap, "Rating");
    }
}

The assembly is connected through the <Plugins> section in FastReport.config or by a direct call at application startup. A ready-made example of such a plugin — Extras/Misc/TeeChartObjectPlugin in FastReport .NET.

While the class is not deployed, the server will not be able to read the report with this object and will throw ClassException — including when building the preview. The designer build without the plugin will nevertheless open the report and save the unknown object with its tag, attributes and nested XML elements.

 


 

What next

The plugin can do more than shown in the article: inherit the behavior of the standard components via extends, connect custom property editors via registerPropertyEditor and use third-party libraries — they are installed via npm install <package> and packed together with node_modules. All this is described in the «Custom components» chapter of the Online Designer user manual, and the DemoChartObject example shows these techniques in working code.

 


 

Frequently asked questions

Can you do without a .NET class?

Yes, the JS plugin is enough for working in the designer. But without a class on the server, a report with this component cannot be built: the server will throw ClassException.

How to set your own icon in the palette?

Specify in palette.icon your own SVG or PNG as a data:-URI. Without it, the SDK will substitute the standard icon.

What to check if the builder rejected the archive?

There must be a single plugin folder at the root of the archive, and in it — the file index.jsx or index.js. The builder will show the list of problems right away at upload.

 


 

Conclusion

A custom component for FastReport Online Designer — two halves tied together by the same type name: a JS plugin for the editor and a .NET class for the server. To assemble everything today, download the SDK, copy the DemoChartObject example and substitute your own properties, preview and settings dialog — the designer will be rebuilt together with the plugin. Connect the server-side part in parallel: even before the class is deployed, a report with the new component can be opened and saved without losses.

FastReport Online Designer Designer Customization
October 26, 2026

Progress Bar in Delphi: The TfrProgressBar and TfrxProgressBar Components from FastReport VCL

Let’s take a closer look at the TfrProgressBar and TfrxProgressBar components from FastReport VCL: configuring the progress scale, thresholds and markers, binding to data, and a Delphi example.
October 26, 2026

TfrImageComboBox: A drop-down list with images and text captions in FastReport VCL

TfrImageComboBox from FastEditors VCL: a drop-down list with icons and labels for FastReport VCL. Properties, events, and usage examples in Delphi.
October 12, 2026

GS1 DataBar Expanded Stacked: Features and Configuration in FastReport .NET

GS1 DataBar Expanded Stacked barcode guide: multi-line encoding of GTIN, expiration dates, weights, and batch numbers. Learn about data structure, scanning, and FastReport .NET Segments configuration.

© 1998-2026 Fast Reports Inc.