Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Components/Charts/Chart/Renderer/ChartElementRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
return;
}

if (IsStaticSSR())
{
SetDefaultRendererValues();
}

this.CreateCascadingValue(builder, 0, 1, this, 2,
BuildRenderers);
RendererShouldRender = false;
Expand Down Expand Up @@ -203,6 +208,13 @@ internal void SetDefaultRendererContainerValues()
internal void Prerender()
{
ContainerUpdate = true;

if (IsStaticSSR())
{
ContainerPrerender = true;
RendererShouldRender = true;
SetDefaultRendererValues();
}
_ = InvokeAsync(StateHasChanged);
}
#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,10 @@ private static void CreateSeriesNestedElements(RenderTreeBuilder builder, ChartS
{
int seq = 0;
ChartSeries series = element;
if (series.Marker?.RendererType is not null)

bool shouldOpenMarker = series.Marker?.RendererType is not null &&
(series.Marker.Visible || series.Marker.DataLabel.Visible);
if (shouldOpenMarker)
{
builder.OpenComponent(seq++, series.Marker.RendererType);
builder.AddAttribute(seq++, "Series", series);
Expand Down Expand Up @@ -972,14 +975,21 @@ internal override void SetDefaultRendererValues()
ProcessData();
Owner?._legendRenderer?.SetDefaultRendererValues();
Owner?._axisContainer?.SetDefaultRendererContainerValues();
}
catch
{
if (!IsDisposed)
if (Owner?.InitialRect is not null)
{
throw;
HandleChartSizeChange(Owner.InitialRect);
foreach (var seriesRenderer in Renderers.OfType<ChartSeriesRenderer>())
{
seriesRenderer.Series?.Marker?.Renderer?.HandleChartSizeChange(Owner.InitialRect);
}
Owner?._striplineBehindContainer?.SetDefaultRendererValues();
Owner?._striplineOverContainer?.SetDefaultRendererValues();
}
}
catch (Exception exception) when (IsDisposed)
{
System.Diagnostics.Debug.WriteLine($"Chart series renderer initialization failed during disposal: {exception}");
}
}

internal void OnThemeChanged()
Expand Down Expand Up @@ -1099,6 +1109,19 @@ public override void HandleChartSizeChange(Rect rect)
{
renderer.HandleChartSizeChange(rect);
}

if (IsStaticSSR())
{
// Markers again if they were null during series pass
foreach (var seriesRenderer in Renderers.OfType<ChartSeriesRenderer>())
{
seriesRenderer.Series?.Marker?.Renderer?.HandleChartSizeChange(rect);
}

// Striplines after axis + series clip are final
Owner?._striplineBehindContainer?.UpdateStriplineCollection();
Owner?._striplineOverContainer?.UpdateStriplineCollection();
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ internal class ChartMarkerRenderer : ChartRenderer, IChartElementRenderer
#region Fields
private string? _seriesIndex;
private List<SymbolOptions> _symbolOptions = [];
// Static SSR is allowed once; subsequent passes use the normal renderer gate.
private bool _staticSSRRenderPending = true;
#endregion

#region Properties
Expand Down Expand Up @@ -359,6 +361,16 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
RenderMarkers(builder);
builder.CloseElement();
}

if (IsStaticSSR())
{
_staticSSRRenderPending = false;
}
}

protected override bool ShouldRender()
{
return RendererShouldRender || (IsStaticSSR() && _staticSSRRenderPending);
}

#endregion
Expand All @@ -377,7 +389,7 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
/// <returns>Calculated SymbolOptions instance.</returns>
internal static SymbolOptions CalculateSymbol(ChartEventLocation location, string shape, Size size, string url, PathOptions option, SfChart chart)
{
ChartEventLocation currentLocation = null!;
ChartEventLocation currentLocation = chart.IsStaticServerRendering() ? location : null!;
if (chart is not null && shape == "Circle")
{
string[] locations = ChartHelper.AppendTextElements(chart, option.Id, location.X, location.Y, "cx", "cy");
Expand All @@ -388,7 +400,10 @@ internal static SymbolOptions CalculateSymbol(ChartEventLocation location, strin

if (shapeoption.ShapeName == ShapeName.Path)
{
shapeoption.PathOption.Direction = ChartHelper.AppendPathElements(chart ?? null!, shapeoption.PathOption.Direction, shapeoption.PathOption.Id);
if (chart != null)
{
shapeoption.PathOption.Direction = ChartHelper.AppendPathElements(chart, shapeoption.PathOption.Direction, shapeoption.PathOption.Id);
}
shapeoption.PathOption.Visibility = option.Visibility;
}

Expand Down Expand Up @@ -506,6 +521,20 @@ internal void UpdateMarkerBorderWidth()
}
}

/// <summary>
/// SSR entry point – computes marker symbols when OnAfterRenderAsync is unavailable.
/// </summary>
internal override void SetDefaultRendererValues()
{
SeriesRenderer = Series?.Renderer;
if (SeriesRenderer != null && (Series?.Marker?.Visible ?? false))
{
CalculateRenderTreeBuilderOptions(); // fills _symbolOptions
SeriesRenderer.CalculateMarkerClipPath();
}
RendererShouldRender = true;
}

#endregion

#region Public Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ internal override void SetDefaultRendererValues()
{
ClipRect = Owner._axisContainer.AxisLayout.SeriesClipRect ?? null!;
}

HandleChartSizeChange(Owner?.InitialRect ?? new Rect(0, 0, 0, 0));
RendererShouldRender = true;
}
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,18 @@ internal void UpdateCustomization(string property)
}
}

/// <summary>
/// SSR entry point – calculates stripline geometry when OnAfterRenderAsync is unavailable.
/// </summary>
internal override void SetDefaultRendererValues()
{
if (Stripline != null)
{
InitStripline(); // this is the method that already exists and fills the path/rect collections
}
RendererShouldRender = true;
}

#endregion

#region Public Methods
Expand Down
26 changes: 22 additions & 4 deletions src/Components/Charts/Chart/Series/Marker/ChartMarker.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.ComponentModel;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Syncfusion.Blazor.Toolkit.Charts.Internal;
using System.ComponentModel;

namespace Syncfusion.Blazor.Toolkit.Charts
{
Expand Down Expand Up @@ -99,9 +100,26 @@ private void UpdateLegend()
/// </summary>
private void SetDefaultRendererValues()
{
if (Series?.Container is not null && Series.Renderer is not null && Series.Renderer.IsStaticSSR())
// Guard everything – any of these can still be null on the first SSR pass
if (Series == null || Series.Container == null || Series.Renderer == null)
{
Series.Container._seriesContainer?.Prerender();
return;
}

if (!Series.Renderer.IsStaticSSR())
{
return;
}

// 1. Force the series container to run its layout / prerender
Series.Container._seriesContainer?.Prerender();

// Recalculate symbols when the marker renderer component already exists.
var markerRenderer = Series.Marker?.Renderer;
if (markerRenderer != null)
{
var rect = Series.Container.InitialRect ?? new Rect(0, 0, 0, 0);
markerRenderer.HandleChartSizeChange(rect);
}
}

Expand Down
22 changes: 16 additions & 6 deletions src/Components/Charts/Chart/SfChart.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ private double GetInitialCoordinate(double adaptiveMargin, double staticMargin,
private void CalculateAvailableSize()
{
double height = Height != NullDimensionValue ? ChartHelper.StringToNumber(Height, _elementOffset.Height) : ChartDefaultHeight;
double width = Width != NullDimensionValue ? ChartHelper.StringToNumber(Width, _elementOffset.Width) : ChartDefaultHeight;
double width = Width != NullDimensionValue ? ChartHelper.StringToNumber(Width, _elementOffset.Width) : ChartDefaultWidth;

AvailableSize = new Size(width > 0 ? width : AvailableSize.Width, height > 0 ? height : AvailableSize.Height);
if (EnableAdaptiveRendering)
Expand Down Expand Up @@ -1718,16 +1718,26 @@ internal void InitializeStaticChart()
{
if (!_render.IsSizeSet)
{
// Force defaults when no DOM measurement is possible
if (_elementOffset.Width <= 0 || _elementOffset.Height <= 0)
{
_svgWidth ??= ChartDefaultWidth.ToString(CultureInfo.InvariantCulture);
_svgHeight ??= ChartDefaultHeight.ToString(CultureInfo.InvariantCulture);
}

CalculateAvailableSize();
SetInitialRect();

// Border initialization reaches this method before the normal layout pass;
// process data first so the synchronous prerender sees populated renderers.
// IsSizeSet keeps this SSR-only initialization from repeating.
ProcessData();
Prerender();
}
}
catch
catch (Exception exception) when (IsDisposed)
{
if (!IsDisposed)
{
throw;
}
System.Diagnostics.Debug.WriteLine($"Static chart initialization failed during disposal: {exception}");
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/Components/Charts/Common/ChartUtils/ChartHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,14 @@ internal static string AppendPathElements(SfChart chart, string direction, strin
/// <returns>An array containing the string representation of X and Y coordinates.</returns>
internal static string[] AppendTextElements(SfChart chart, string id, double locationX, double locationY, string x = "x", string y = "y")
{
if (chart == null && chart.IsStaticServerRendering())
{
return new string[]
{
locationX.ToString(CultureInfo.InvariantCulture),
locationY.ToString(CultureInfo.InvariantCulture)
};
}
bool redraw = chart._redraw;

if (chart._textAnimationElements.TryGetValue(id, out DynamicTextAnimationOptions? existElement))
Expand Down
Loading