Renderiza un gráfico de barras configurando Type="bar" el FluentUIChart componente. Pasar una lista de etiquetas de categoría y uno o más ChartDataset objetos para definir las barras. FluentUIChart es un envoltorio consciente del tema alrededor del componente subyacente Chart , que se construye sobre Chart.js.
Un gráfico de barras con tres conjuntos de datos sin colorear — los colores se rellenan desde la paleta activa de Fluent. Haz clic en cualquier barra para ver la carga útil del evento de clic, y cambia el tema del sitio entre Luz y Oscuridad para ver cómo el gráfico se re-temaza.
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 se renderiza a un HTML <canvas>, por lo que el CSS no puede acceder a barras, etiquetas de ejes o líneas de cuadrícula — son píxeles rasterizados. FluentUIChart Soluciona esto leyendo las propiedades personalizadas resueltas del CSS en tiempo de renderizado y enviando los valores a las opciones de Chart.js como color, scale.ticks.color, y scale.grid.color. Se suscribe y ThemeService.ThemeChanged vuelve a aplicar la paleta cada vez que cambia el tema.
Los conjuntos de datos que salen BackgroundColor o BorderColor nulos se rellenan automáticamente a partir de una paleta de series derivada de Fluent que comienza con el color de acento actual. Los conjuntos de datos que proporcionan colores explícitos se pasan sin cambios.
Suscríbete para OnElementClick recibir una notificación cuando el usuario haga clic en una barra (o en cualquier elemento renderizado). La callback recibe un ChartClickEventArgs con el índice del conjunto de datos, índice de datos, etiqueta, valor, etiqueta del conjunto de datos y la instancia original IDataPoint . Subclase DataPoint para adjuntar el contexto definido por el llamador (id de registro, región, categoría, etc.) y hacer coincidencia de patrones con tu subclase en el handler de clics para recuperarla. Se ignoran los clics en el fondo del gráfico.
import {
ChartType,
type BaseDataPoint,
type ChartClickEventArgs,
type ChartDataset,
} from '@powerportalspro/react-charts';
import { FluentUIChart } from '@powerportalspro/react-fluent';
// Extiende BaseDataPoint para adjuntar el contexto definido por el llamador (región, id de registro,
// categoría, etc.). Parametrización <FluentUIChart> con este tipo a continuación</FluentUIChart>
// Lo fluye a args.dataPoint — no se requieren 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 coincidencia de patrones. DataPoint para recuperar cualquier contexto definido por el llamante.
if (args.DataPoint is SalesDataPoint sdp)
{
Console.WriteLine($"{args.Label}: {sdp.Value} ({sdp.Region})");
}
}
}Configura Title para mostrar un encabezado encima del gráfico. El título está representado por Chart.js dentro del lienzo y utiliza el color del texto del tema actual.
<DataverseChart dataSource={source}
type={ChartType.Bar}
title="Ingresos por año" /><DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Ingresos por año" />Configura Stacked="true" para apilar conjuntos de datos unos sobre otros en lugar de uno al lado del otro. Esto es útil para gráficos de barras y líneas con múltiples series donde el total en todas las series es significativo (por ejemplo, ingresos totales = ganado + perdido).
<DataverseChart dataSource={source}
type={ChartType.Bar}
stacked /><DataverseChart Source="_source"
Type="ChartType.Bar"
Stacked="true" />Configura LegendPosition para controlar dónde aparece la leyenda: "top" (por defecto), "bottom", "left", "right", o "hidden" para ocultarla por completo.
// Posición: Arriba (por defecto), Abajo, Izquierda, Derecha
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Bottom} />
// Oculta la leyenda por completo
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Hidden} /><!-- Posición: Arriba (por defecto), Abajo, Izquierda, Derecha -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Bottom" />
<!-- Oculta la leyenda por completo -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Hidden" />Úsalo AggregateDataverseChartDataSource para alimentar un gráfico de Dataverse sin escribir FetchXML en bruto. Establece TableName, GroupByColumn, AggregateColumn, y Aggregate. Opcionalmente, añade un SeriesColumn para multi-series, un GroupByDateGrouping para bucketing de fechas, un ViewId para fusionar las condiciones de filtro de una vista guardada, o un FilterXml fragmento para condiciones en línea.
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 mantiene estable la identidad de la fuente para que el gráfico no lo haga
// re-fitch en cada renderizado — se aplican cambios en la configuración en el montaje.
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. Etiqueta, args. Valor, args. DataPoint
}
}Ingresos estimados por oportunidades por año, divididos por estado (Ganados vs Perdidos) y apilados — cargados desde Dataverse vía AggregateDataverseChartDataSource. Haz clic en una barra para ver el año, el estado y los ingresos.
Pasa ViewIds y DefaultViewId sigue DataverseChart mostrando un desplegable selector de vistas sobre el gráfico. Cuando el usuario cambia de vista, las condiciones de filtro de la vista seleccionada se fusionan en la consulta agregada y el gráfico se recarga. El ViewId on no se establece directamente — DataverseChart lo gestiona. La vista determina qué registros se incluyen; La configuración agregada determina cómo se agrupan y resumen.
import {
AggregateDataverseChartDataSource,
AggregateType,
ChartDateGrouping,
ChartType,
} from '@powerportalspro/react-charts';
import { DataverseChart } from '@powerportalspro/react-fluent';
import { useMemo } from 'react';
const VIEW_IDS = [
'...', // Oportunidades ganadas
'...', // Todas las 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 ganadas
new Guid("..."), // Todas las 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,
};
}Ingresos estimados por mes con un desplegable selector de vistas. Cambia entre vistas para ver cómo se recarga el gráfico con diferentes criterios de filtro.
Establece GroupByLinkedEntity (o SeriesLinkedEntity) para agrupar o dividir por una columna en una tabla relacionada. El constructor crea una <link-entity> unión y coloca el groupby atributo dentro de ella. Soporta anidamiento ilimitado para ChartLinkedEntity.LinkedEntity uniones 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="Ingresos por industria"
yAxisPrefix="$"
/>
);
}<DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Ingresos por industria"
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,
};
}La configuración anterior genera el siguiente 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>
Ingresos totales estimados por oportunidades agrupados por la industria de la cuenta matriz — la industrycode columna sigue sobre la account mesa, unida a través de customerid.
Véase también