Renderize um gráfico de barras configurando Type="bar" o FluentUIChart componente. Passe uma lista de etiquetas de categorias e um ou mais ChartDataset objetos para definir as barras. FluentUIChart é um wrapper consciente do tema ao redor do componente subjacente Chart , que é construído sobre Chart.js.
Um gráfico de barras com três conjuntos de dados sem cor — as cores são preenchidas a partir da paleta ativa do Fluent. Clique em qualquer barra para ver o payload do evento de clicar e alterne o tema do site entre Luz e Escuro para ver o gráfico re-tema no lugar.
import { ChartType, type ChartDataset } from '@powerportalspro/react-charts';
import { FluentUIChart } from '@powerportalspro/react-fluent';
const LABELS = ['Jan', 'Feb', 'Mar'];
const DATASETS: ChartDataset[] = [
{
label: 'Sales',
data: [{ value: 65 }, { value: 59 }, { value: 80 }],
},
{
label: 'Returns',
data: [{ value: 12 }, { value: 19 }, { value: 8 }],
},
];
export function MyChart() {
return <FluentUIChart type={ChartType.Bar} labels={LABELS} datasets={DATASETS} />;
}<FluentUIChart Type="ChartType.Bar"
Labels="_labels"
Datasets="_datasets" />
@code {
private List<string> _labels = new() { "Jan", "Feb", "Mar" };
private List<ChartDataset> _datasets = new()
{
new ChartDataset
{
Label = "Sales",
Data = new List<DataPoint>
{
new DataPoint(65), new DataPoint(59), new DataPoint(80),
},
},
new ChartDataset
{
Label = "Returns",
Data = new List<DataPoint>
{
new DataPoint(12), new DataPoint(19), new DataPoint(8),
},
},
};
}Chart.js renderiza para um HTML <canvas>, então o CSS não pode alcançar barras, rótulos de eixo ou linhas de grade — são pixels rasterizados. FluentUIChart Contorna isso lendo as propriedades personalizadas resolvidas do CSS em tempo de renderização e inserindo os valores nas opções de Chart.js como color, scale.ticks.color, e scale.grid.color. Ele assina ThemeService.ThemeChanged e reaplica a paleta sempre que o tema muda.
Conjuntos de dados que saem BackgroundColor ou BorderColor são nulos são preenchidos automaticamente a partir de uma paleta de séries derivada do Fluent, começando pela cor de destaque atual. Conjuntos de dados que fornecem cores explícitas são passados inalterados.
Inscreva-se OnElementClick para ser notificado quando o usuário clicar em uma barra (ou qualquer elemento renderizado). O callback recebe um ChartClickEventArgs com o índice do conjunto de dados, índice de dados, etiqueta, valor, rótulo do conjunto de dados e a instância original IDataPoint . Subclasse DataPoint para anexar contexto definido pelo chamador (id de registro, região, categoria, etc.) e fazer pattern-match com sua subclasse no handler de clique para recuperá-la. Cliques no fundo do gráfico são ignorados.
import {
ChartType,
type BaseDataPoint,
type ChartClickEventArgs,
type ChartDataset,
} from '@powerportalspro/react-charts';
import { FluentUIChart } from '@powerportalspro/react-fluent';
// Estenda o BaseDataPoint para anexar contexto definido pelo chamador (região, id de registro,
// categoria, etc.). Parametrização <FluentUIChart> com esse tipo abaixo</FluentUIChart>
// O fluxo para args.dataPoint — não é necessário fazer casts.
interface SalesDataPoint extends BaseDataPoint {
region: string;
}
const DATASETS: ChartDataset<SalesDataPoint>[] = [/* ... */];
function onBarClicked(args: ChartClickEventArgs<SalesDataPoint>) {
const region = args.dataPoint?.region ?? '';
console.log(`${args.label}: ${args.value} (${region})`);
}
export function MyChart() {
return (
<FluentUIChart<SalesDataPoint>
type={ChartType.Bar}
labels={LABELS}
datasets={DATASETS}
onElementClick={onBarClicked}
/>
);
}<FluentUIChart Type="ChartType.Bar"
Labels="_labels"
Datasets="_datasets"
OnElementClick="OnBarClicked" />
@code {
private class SalesDataPoint : DataPoint
{
public SalesDataPoint(double value) : base(value) { }
public string Region { get; set; } = string.Empty;
}
private void OnBarClicked(ChartClickEventArgs args)
{
// Args de correspondência de padrões. DataPoint para recuperar qualquer contexto definido pelo chamador.
if (args.DataPoint is SalesDataPoint sdp)
{
Console.WriteLine($"{args.Label}: {sdp.Value} ({sdp.Region})");
}
}
}Configure Title para exibir um cabeçalho acima do gráfico. O título é renderizado por Chart.js dentro da tela e usa a cor do texto do tema atual.
<DataverseChart dataSource={source}
type={ChartType.Bar}
title="Receita por Ano" /><DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Receita por Ano" />Configurado Stacked="true" para empilhar conjuntos de dados uns sobre os outros em vez de lado a lado. Isso é útil para gráficos de barras e linhas com múltiplas séries, onde o total de todas as séries é significativo (por exemplo, receita total = ganho + derrotado).
<DataverseChart dataSource={source}
type={ChartType.Bar}
stacked /><DataverseChart Source="_source"
Type="ChartType.Bar"
Stacked="true" />Defina LegendPosition para controlar onde a legenda aparece: "top" (padrão), "bottom", "left", "right", ou "hidden" para ocultá-la completamente.
// Posição: Cima (padrão), Baixo, Esquerda, Direita
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Bottom} />
// Esconda a lenda completamente
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Hidden} /><!-- Posição: Cima (padrão), Baixo, Esquerda, Direita -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Bottom" />
<!-- Esconda a lenda completamente -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Hidden" />Uso AggregateDataverseChartDataSource para alimentar um gráfico do Dataverse sem escrever FetchXML bruto. Defina TableName, GroupByColumn, AggregateColumn, e Aggregate. Opcionalmente, adicione um SeriesColumn para multi-série, um GroupByDateGrouping para bucketing de data, um ViewId para mesclar as condições de filtro de uma visualização salva, ou um FilterXml fragmento para condições inline.
import {
AggregateDataverseChartDataSource,
AggregateType,
ChartDateGrouping,
ChartType,
type ChartClickEventArgs,
} from '@powerportalspro/react-charts';
import { DataverseChart } from '@powerportalspro/react-fluent';
import { useMemo } from 'react';
export function MyChart() {
// useMemo mantém a identidade da fonte estável para que o gráfico não fique
// Re-busca em cada renderização — mudanças na configuração são aplicadas na montagem.
const source = useMemo(
() =>
new AggregateDataverseChartDataSource({
tableName: 'opportunity',
groupByColumn: 'actualclosedate',
groupByDateGrouping: ChartDateGrouping.Year,
aggregateColumn: 'estimatedvalue',
aggregate: AggregateType.Sum,
seriesColumn: 'statecode',
filterXml:
"<filter><condition attribute='statecode' operator='ne' value='0' /></filter>",
}),
[],
);
const onBarClicked = (args: ChartClickEventArgs) => {
// args.datasetLabel, args.label, args.value, args.dataPoint
};
return (
<DataverseChart
dataSource={source}
type={ChartType.Bar}
title="Estimated Revenue by Year (Stacked)"
stacked
yAxisPrefix="$"
onElementClick={onBarClicked}
/>
);
}<DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Estimated Revenue by Year (Stacked)"
Stacked="true"
YAxisPrefix="$"
OnElementClick="OnBarClicked" />
@code {
private readonly AggregateDataverseChartDataSource _source = new()
{
TableName = "opportunity",
GroupByColumn = "actualclosedate",
GroupByDateGrouping = ChartDateGrouping.Year,
AggregateColumn = "estimatedvalue",
Aggregate = AggregateType.Sum,
SeriesColumn = "statecode",
FilterXml = "<filter><condition attribute='statecode' operator='ne' value='0' /></filter>",
};
private void OnBarClicked(ChartClickEventArgs args)
{
// args. DatasetLabel, args. Selo, args. Valor, args. DataPoint
}
}Receita estimada de oportunidades por ano, dividida por status (Ganho vs Perdido) e empilhada — carregada do Dataverse via AggregateDataverseChartDataSource. Clique em uma barra para ver o ano, status e receita.
Passe ViewIds e DefaultViewId siga DataverseChart para exibir um menu suspenso do seletor de visualização acima do gráfico. Quando o usuário troca de vista, as condições de filtro da vista selecionada são mescladas na consulta agregada e o gráfico é recarregado. O ViewId na fonte não é definido diretamente — DataverseChart ele gerencia. A visualização determina quais registros estão incluídos; A configuração agregada determina como eles são agrupados e resumidos.
import {
AggregateDataverseChartDataSource,
AggregateType,
ChartDateGrouping,
ChartType,
} from '@powerportalspro/react-charts';
import { DataverseChart } from '@powerportalspro/react-fluent';
import { useMemo } from 'react';
const VIEW_IDS = [
'...', // Oportunidades Conquistadas
'...', // Todas as Oportunidades
];
const DEFAULT_VIEW_ID = VIEW_IDS[0];
export function MyChart() {
const source = useMemo(
() =>
new AggregateDataverseChartDataSource({
tableName: 'opportunity',
groupByColumn: 'actualclosedate',
groupByDateGrouping: ChartDateGrouping.MonthAndYear,
aggregateColumn: 'estimatedvalue',
aggregate: AggregateType.Sum,
}),
[],
);
return (
<DataverseChart
dataSource={source}
type={ChartType.Bar}
viewIds={VIEW_IDS}
defaultViewId={DEFAULT_VIEW_ID}
yAxisPrefix="$"
/>
);
}<DataverseChart Source="_source"
Type="ChartType.Bar"
ViewIds="_viewIds"
DefaultViewId="@_defaultViewId"
YAxisPrefix="$" />
@code {
private static readonly List<Guid> _viewIds = new()
{
new Guid("..."), // Oportunidades Conquistadas
new Guid("..."), // Todas as Oportunidades
};
private static readonly Guid _defaultViewId = _viewIds[0];
private readonly AggregateDataverseChartDataSource _source = new()
{
TableName = "opportunity",
GroupByColumn = "actualclosedate",
GroupByDateGrouping = ChartDateGrouping.MonthAndYear,
AggregateColumn = "estimatedvalue",
Aggregate = AggregateType.Sum,
};
}Receita estimada por mês com um menu suspenso de seletor de visualizações. Alterne entre as vistas para ver o gráfico recarregar com critérios de filtro diferentes.
Defina GroupByLinkedEntity (ou SeriesLinkedEntity) para agrupar ou se dividir por uma coluna em uma tabela relacionada. O construtor cria uma <link-entity> junção e coloca o groupby atributo dentro dela. Suporta aninhamento ilimitado via ChartLinkedEntity.LinkedEntity para joins multi-hop.
import {
AggregateDataverseChartDataSource,
AggregateType,
ChartType,
} from '@powerportalspro/react-charts';
import { DataverseChart } from '@powerportalspro/react-fluent';
import { useMemo } from 'react';
export function MyChart() {
const source = useMemo(
() =>
new AggregateDataverseChartDataSource({
tableName: 'opportunity',
groupByColumn: 'industrycode',
groupByLinkedEntity: {
tableName: 'account',
from: 'accountid',
to: 'customerid',
},
aggregateColumn: 'estimatedvalue',
aggregate: AggregateType.Sum,
}),
[],
);
return (
<DataverseChart
dataSource={source}
type={ChartType.Bar}
title="Receita por Indústria"
yAxisPrefix="$"
/>
);
}<DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Receita por Indústria"
YAxisPrefix="$" />
@code {
private readonly AggregateDataverseChartDataSource _source = new()
{
TableName = "opportunity",
GroupByColumn = "industrycode",
GroupByLinkedEntity = new ChartLinkedEntity
{
TableName = "account",
From = "accountid",
To = "customerid",
},
AggregateColumn = "estimatedvalue",
Aggregate = AggregateType.Sum,
};
}A configuração acima gera o seguinte FetchXML:
<fetch aggregate="true">
<entity name="opportunity">
<attribute name="estimatedvalue" alias="estimatedvalue" aggregate="sum" />
<link-entity name="account" from="accountid" to="customerid" link-type="inner">
<attribute name="industrycode" alias="industrycode" groupby="true" />
<order alias="industrycode" />
</link-entity>
</entity>
</fetch>
Receita total estimada de oportunidades agrupada pelo setor da conta-mãe — a industrycode coluna fica na account mesa, unida via customerid.
Veja também