Como adicionar seu próprio componente ao FastReport Online Designer

2026-11-10

Como adicionar seu próprio componente ao FastReport Online Designer

FastReport Online Designer permite adicionar seus próprios componentes de relatório — com o seu ícone na paleta, propriedades no painel Properties e a sua caixa de diálogo de configurações. Nada de mágica: você escreve um plugin em JavaScript, faz o upload dele para o builder e ele é compilado diretamente na build do designer.

Neste artigo criaremos um componente chamado «Avaliação» do zero, que exibe um valor em forma de estrelas, e percorreremos todo o caminho: do download do SDK até uma build pronta do designer com o plugin e a parte do servidor.

 


 

Como um componente personalizado é estruturado

O componente tem duas metades:

  • Plugin JS é responsável pela edição no navegador: a visualização na página, as propriedades no painel, a caixa de diálogo de configurações e o salvamento em .frx.
  • .NET class roda no seu servidor e é responsável pela construção do relatório e de sua visualização.

O que as liga é o nome do tipo: o nome curto da classe .NET, o campo type no plugin e a tag XML no .frx devem ser uma e a mesma string.

As duas metades podem ser feitas uma após a outra. A classe .NET não é necessária para o designer, por isso primeiro construiremos e testaremos o plugin, e a parte do servidor será adicionada no final.

 


 

Passo 1. Baixe o SDK e prepare a pasta do plugin

No builder, abra Build → Componentes personalizados e clique em Baixar SDK. O ZIP contém README.md com uma breve introdução e examples/DemoChartObject — um exemplo funcional.

A pasta do plugin também serve como pasta de trabalho para a sua IDE. Copie examples/DemoChartObject e renomeie a cópia para RatingObject: nela já está tudo pronto para o autocompletar — sdk.d.ts com os tipos do SDK, jsconfig.json e package.json com os tipos do React correspondentes à versão do React do designer. Execute npm install nesta pasta e abra-a na sua IDE.

 

Passo 2. Descreva o componente

Um plugin — uma pasta com o arquivo index.jsx (ou index.js). Substitua o conteúdo de RatingObject/index.jsx pela descrição do componente:

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'},
  ],
});

Isso já é suficiente para o componente aparecer na paleta e receber suas propriedades:

  • palette define o cartão na paleta. O ícone aqui é o padrão, mas você também pode indicar o seu próprio SVG ou PNG como um data:-URI.
  • defaultValues armazena os valores padrão. Somente os valores diferentes deles vão para o .frx — funciona da mesma forma que o FastReport .NET.
  • properties descreve os campos do painel de propriedades no formato Categoria:Nome. Os campos Design:Name and Layout:Left/Top/Width/Height são adicionados pelo próprio SDK.

Não é preciso salvar e ler .frx manualmente: a implementação herdada já sabe trabalhar com todas as propriedades declaradas.

 

Passo 3. Desenhe a visualização

Para que o componente pareça uma avaliação na página, adicione o draw à descrição. A moldura, a movimentação e o redimensionamento são fornecidos ao componente pela classe base Component, portanto draw é responsável apenas pelo conteúdo. O desenho deve ser feito no contêiner this.$content: no momento da chamada, ele já foi criado.

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('');
},

 

Passo 4. Adicione a caixa de diálogo de configurações

A caixa de diálogo de configurações abre com um duplo clique no componente. Vamos montá-la com os controles padrão de sdk/controls, para que fique com a aparência dos editores integrados:

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>
  );
}

Os controles gravam as alterações em component.model. Isso é um rascunho: as propriedades reais do componente só são alteradas após submit(), portanto o botão Cancelar não estraga nada.

Conecte a caixa de diálogo na descrição do componente:

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

 

Passo 5. Traduza os textos

O plugin deve conter suas próprias traduções. É conveniente usar o texto em inglês como chave: se não houver tradução, o designer mostrará a própria chave.

const TRANSLATIONS = {
  en: {'Rating': 'Rating', 'Star rating': 'Star rating', 'Value': 'Value', 'Maximum': 'Maximum', 'Star color': 'Star color', 'Cancel': 'Cancel'},
  'pt-BR': {'Rating': 'Avaliação', 'Star rating': 'Avaliação em estrelas', 'Value': 'Valor', 'Maximum': 'Máximo', 'Star color': 'Cor das estrelas', 'Cancel': 'Cancelar'},
};

Adicione a linha translations: TRANSLATIONS à descrição do componente. As legendas na paleta e no painel de propriedades o designer traduzirá por conta própria; em seu próprio código use tr('Value').

 

Passo 6. Faça upload do plugin e construa o designer

  1. Empacote no ZIP a própria pasta do plugin, e não o seu conteúdo: o ZIP deve conter uma única pasta raiz RatingObject. Não é preciso excluir node_modules antes de empacotar — o builder levará em conta apenas os pacotes de dependencies, enquanto devDependencies (incluindo os tipos do React) não entrarão na build.
  2. Na página Build → Componentes personalizados clique em Fazer upload do plugin. O ZIP é verificado imediatamente: se algo estiver errado, você verá uma lista de problemas. A versão anterior do plugin permanecerá no lugar.
  3. O plugin aparecerá na lista já verificado. Inicie a build e baixe o designer.

Abra o designer:  Avaliação apareceu na paleta. Adicione-o à página, mude o valor no painel de propriedades e abra a caixa de diálogo de configurações com um duplo clique.

Se você constrói o designer via Builder API, faça o upload do ZIP com uma requisição POST /builderAPI/extensions e liste os plugins na requisição de build: "extensions": ["RatingObject"].

 

Passo 7. Adicione a parte do servidor

Para que o servidor possa construir um relatório com o novo objeto, é necessária uma classe .NET com o mesmo nome em uma assembly separada:

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

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

A assembly é conectada pela seção <Plugins> em FastReport.config ou por uma chamada direta na inicialização do aplicativo. Um exemplo pronto de tal plugin — Extras/Misc/TeeChartObjectPlugin no FastReport .NET.

Enquanto a classe não estiver implantada, o servidor não conseguirá ler o relatório com esse objeto e lançará ClassException — inclusive ao gerar a visualização. A build do designer sem o plugin, no entanto, abrirá o relatório e salvará o objeto desconhecido com sua tag, seus atributos e os elementos XML aninhados.

 


 

O que fazer a seguir

O plugin sabe fazer mais do que o mostrado no artigo: herdar o comportamento dos componentes padrão via extends, conectar editores de propriedades próprios via registerPropertyEditor e usar bibliotecas de terceiros — elas são instaladas via npm install <pacote> e empacotadas junto com node_modules. Tudo isso está descrito no capítulo «Componentes personalizados» do manual do usuário do Online Designer, e o exemplo DemoChartObject mostra essas técnicas em código funcional.

 


 

Perguntas frequentes

É possível dispensar a classe .NET?

Sim, para trabalhar no designer basta o plugin JS. Mas, sem a classe no servidor, não será possível construir um relatório com esse componente: o servidor lançará ClassException.

Como definir um ícone próprio na paleta?

Indique em palette.icon o seu próprio SVG ou PNG como um data:-URI. Sem ele, o SDK usará o ícone padrão.

O que verificar se o builder rejeitou o ZIP?

Na raiz do ZIP deve haver uma única pasta de plugin, e nela — o arquivo index.jsx ou index.js. O builder mostrará a lista de problemas já no upload.

 


 

Conclusão

Um componente personalizado para o FastReport Online Designer — duas metades amarradas pelo mesmo nome de tipo: um plugin JS para o editor e uma classe .NET para o servidor. Para montar tudo hoje, baixe o SDK, copie o exemplo DemoChartObject e substitua suas próprias propriedades, visualização e caixa de diálogo de configurações — o designer será reconstruído junto com o plugin. Conecte a parte do servidor em paralelo: mesmo antes da implantação da classe, um relatório com o novo componente pode ser aberto e salvo sem perdas.

FastReport Online Designer Designer Customization
26 de outubro de 2026

TfrImageComboBox: Uma lista suspensa com imagens e legendas de texto no FastReport VCL

TfrImageComboBox do FastEditors VCL: uma lista suspensa com ícones e rótulos para o FastReport VCL. Propriedades, eventos e exemplos de uso no Delphi.
26 de outubro de 2026

Barra de progresso no Delphi: os componentes TfrProgressBar e TfrxProgressBar do FastReport VCL

Vamos examinar mais de perto os componentes TfrProgressBar e TfrxProgressBar do FastReport VCL: configuração da escala de progresso, limites e marcadores, vinculação a dados e um exemplo em Delphi.
12 de outubro de 2026

Como Exportar um Relatório do FastReport .NET Acessíveis PDF (PDF/UA-1)

Como exportar um relatório do FastReport .NET como um arquivo em conformidade com a norma PDF/UA-1: configuração por meio da interface do usuário e do código C#, as funções SemanticRole e AltText e a validação.

© 1998-2026 Fast Reports Inc.