Affichez un graphique à barres en posant Type="bar" sur le FluentUIChart composant. Passer une liste d’étiquettes de catégories et un ou plusieurs ChartDataset objets pour définir les barres. FluentUIChart est un enveloppe thématique autour du composant sous-jacent Chart , construit sur Chart.js.
Un graphique à barres avec trois ensembles de données non coloriées — les couleurs sont complétées à partir de la palette active Fluent. Cliquez sur n’importe quelle barre pour voir la charge utile de l’événement de clic, et basculez le thème du site entre Lumière et Obscurité pour voir le thème du graphique reconfiguré.
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 rend en HTML <canvas>, donc le CSS ne peut pas accéder aux barres, aux étiquettes d’axe ou aux lignes de grille — ce sont des pixels rasterisés. FluentUIChart Contourne cela en lisant les propriétés personnalisées du CSS résolues au moment du rendu et en poussant les valeurs dans les options de Chart.js comme color, scale.ticks.color, et scale.grid.color. Il s’abonne à ThemeService.ThemeChanged la palette et la réapplique chaque fois que le thème change.
Les jeux de données qui sortent BackgroundColor ou BorderColor sont nulls sont automatiquement remplis à partir d’une palette de séries dérivée de Fluent en commençant par la couleur d’accent actuelle. Les ensembles de données fournissant des couleurs explicites sont transmis sans modification.
Abonnez-vous pour OnElementClick être informé lorsque l’utilisateur clique sur une barre (ou sur tout élément rendu). Le rappel reçoit un ChartClickEventArgs avec l’index du jeu de données, l’index des données, l’étiquette, la valeur, l’étiquette du jeu de données et l’instance originale IDataPoint . Sous-classe DataPoint pour associer un contexte défini par l’appelant (id d’enregistrement, région, catégorie, etc.) et faire correspondre un pattern à votre sous-classe dans le gestionnaire de clics pour le récupérer. Les clics sur l’arrière-plan du graphique sont ignorés.
import {
ChartType,
type BaseDataPoint,
type ChartClickEventArgs,
type ChartDataset,
} from '@powerportalspro/react-charts';
import { FluentUIChart } from '@powerportalspro/react-fluent';
// Étendre BaseDataPoint pour attacher un contexte défini par l’appelant (région, id d’enregistrement,
// catégorie, etc.). Paramétrisation <FluentUIChart> avec ce type ci-dessous</FluentUIChart>
// Le fait passer vers args.dataPoint — pas besoin de distribution.
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 par correspondance de schémas. DataPoint pour récupérer tout contexte défini par l’appelant.
if (args.DataPoint is SalesDataPoint sdp)
{
Console.WriteLine($"{args.Label}: {sdp.Value} ({sdp.Region})");
}
}
}Réglez Title pour afficher un titre au-dessus du graphique. Le titre est rendu par Chart.js à l’intérieur de la toile et utilise la couleur du texte du thème actuel.
<DataverseChart dataSource={source}
type={ChartType.Bar}
title="Revenus par année" /><DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Revenus par année" />Configurez Stacked="true" pour empiler les ensembles de données les uns sur les autres plutôt que côte à côte. Cela est utile pour les graphiques à barres et lignes avec plusieurs séries où le total sur toutes les séries a un sens (par exemple, revenu total = gagné + perdu).
<DataverseChart dataSource={source}
type={ChartType.Bar}
stacked /><DataverseChart Source="_source"
Type="ChartType.Bar"
Stacked="true" />Réglez LegendPosition pour contrôler où apparaît la légende : "top" (par défaut), "bottom", "left", "right", ou "hidden" pour la cacher complètement.
// Position : Haut (par défaut), Bas, Gauche, Droite
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Bottom} />
// Cache complètement la légende
<DataverseChart dataSource={source}
legendPosition={ChartLegendPosition.Hidden} /><!-- Position : Haut (par défaut), Bas, Gauche, Droite -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Bottom" />
<!-- Cache complètement la légende -->
<DataverseChart Source="_source"
LegendPosition="ChartLegendPosition.Hidden" />Utilisez-le AggregateDataverseChartDataSource pour alimenter un graphique depuis Dataverse sans écrire du FetchXML brut. Posez TableName, GroupByColumn, AggregateColumn, et Aggregate. En option, ajoutez un SeriesColumn pour multi-séries, un GroupByDateGrouping pour le bucketing de dates, un ViewId pour fusionner les conditions de filtre d’une vue sauvegardée, ou un FilterXml fragment pour les conditions en ligne.
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 maintient l’identité de la source stable pour que le graphique ne le fasse pas
// Re-fetch à chaque rendu — des modifications de la configuration sont appliquées au montage.
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. Label, args. Value, args. DataPoint
}
}Revenus d’opportunités estimés par année, divisés par statut (gagnés vs perdus) et empilés — chargés depuis Dataverse via AggregateDataverseChartDataSource. Cliquez sur une barre pour voir l’année, le statut et les revenus.
Passez ViewIds et DefaultViewId allez DataverseChart afficher un menu déroulant de sélection de vue au-dessus du tableau. Lorsque l’utilisateur change de vue, les conditions de filtre de la vue sélectionnée sont fusionnées dans la requête agrégée et le graphique se recharge. Le ViewId sur la source n’est pas directement défini — DataverseChart il le gère. La vue détermine quels enregistrements sont inclus ; La configuration agrégée détermine comment ils sont regroupés et résumés.
import {
AggregateDataverseChartDataSource,
AggregateType,
ChartDateGrouping,
ChartType,
} from '@powerportalspro/react-charts';
import { DataverseChart } from '@powerportalspro/react-fluent';
import { useMemo } from 'react';
const VIEW_IDS = [
'...', // Opportunités gagnées
'...', // Toutes les opportunités
];
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("..."), // Opportunités gagnées
new Guid("..."), // Toutes les opportunités
};
private static readonly Guid _defaultViewId = _viewIds[0];
private readonly AggregateDataverseChartDataSource _source = new()
{
TableName = "opportunity",
GroupByColumn = "actualclosedate",
GroupByDateGrouping = ChartDateGrouping.MonthAndYear,
AggregateColumn = "estimatedvalue",
Aggregate = AggregateType.Sum,
};
}Chiffre d’affaires estimé par mois avec un menu déroulant de sélection de vues. Passez d’une vue à l’autre pour voir le graphique se recharger avec différents critères de filtrage.
Définir GroupByLinkedEntity (ou SeriesLinkedEntity) pour regrouper ou diviser par une colonne sur une table apparentée. Le constructeur crée une <link-entity> jonction et place l’attribut groupby à l’intérieur. Prend en charge le nœudage illimité via ChartLinkedEntity.LinkedEntity les jointures multi-sauts.
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="Revenus par secteur"
yAxisPrefix="$"
/>
);
}<DataverseChart Source="_source"
Type="ChartType.Bar"
Title="Revenus par secteur"
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 configuration ci-dessus génère le FetchXML suivant :
<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>
Le revenu total estimé des opportunités regroupé par secteur du compte parent — la industrycode chronique reste sur la account table, rejointe via customerid.
Voir aussi