Skip to content
This repository was archived by the owner on Feb 25, 2021. It is now read-only.

Commit 8d6271a

Browse files
Include tree parameters in SetParameters calls
1 parent 702fcdb commit 8d6271a

File tree

2 files changed

+100
-15
lines changed

2 files changed

+100
-15
lines changed

src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using Microsoft.AspNetCore.Blazor.Components;
67
using Microsoft.AspNetCore.Blazor.RenderTree;
78

@@ -18,6 +19,7 @@ internal class ComponentState
1819
private readonly ComponentState _parentComponentState;
1920
private readonly IComponent _component;
2021
private readonly Renderer _renderer;
22+
private readonly IReadOnlyList<TreeParameterState> _treeParameters;
2123
private RenderTreeBuilder _renderTreeBuilderCurrent;
2224
private RenderTreeBuilder _renderTreeBuilderPrevious;
2325
private bool _componentWasDisposed;
@@ -39,6 +41,7 @@ public ComponentState(Renderer renderer, int componentId, IComponent component,
3941
_parentComponentState = parentComponentState;
4042
_component = component ?? throw new ArgumentNullException(nameof(component));
4143
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
44+
_treeParameters = TreeParameterState.FindTreeParameters(this);
4245
_renderTreeBuilderCurrent = new RenderTreeBuilder(renderer);
4346
_renderTreeBuilderPrevious = new RenderTreeBuilder(renderer);
4447
}
@@ -99,7 +102,11 @@ public void NotifyRenderCompleted()
99102

100103
public void SetDirectParameters(ParameterCollection parameters)
101104
{
102-
// TODO: Attach tree parameters also
105+
if (_treeParameters != null)
106+
{
107+
parameters = parameters.WithTreeParameters(_treeParameters);
108+
}
109+
103110
Component.SetParameters(parameters);
104111
}
105112
}

test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7-
using System.Threading.Tasks;
87
using Microsoft.AspNetCore.Blazor.Components;
98
using Microsoft.AspNetCore.Blazor.Rendering;
109
using Microsoft.AspNetCore.Blazor.RenderTree;
@@ -1071,6 +1070,94 @@ public void DoesNotCallOnAfterRenderForComponentsNotRendered()
10711070
Assert.Equal(1, childComponents[2].OnAfterRenderCallCount); // Disposed
10721071
}
10731072

1073+
[Fact]
1074+
public void PassesTreeParametersToNestedComponents()
1075+
{
1076+
// Arrange
1077+
var renderer = new TestRenderer();
1078+
var component = new TestComponent(builder =>
1079+
{
1080+
builder.OpenComponent<Provider<string>>(0);
1081+
builder.AddAttribute(1, "Value", "Hello");
1082+
builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder =>
1083+
{
1084+
childBuilder.OpenComponent<TreeParameterConsumerComponent<string>>(0);
1085+
childBuilder.AddAttribute(1, "RegularParameter", "Goodbye");
1086+
childBuilder.CloseComponent();
1087+
}));
1088+
builder.CloseComponent();
1089+
});
1090+
1091+
// Act/Assert
1092+
var componentId = renderer.AssignRootComponentId(component);
1093+
component.TriggerRender();
1094+
var batch = renderer.Batches.Single();
1095+
var componentFrame = batch.ReferenceFrames.Single(
1096+
frame => frame.FrameType == RenderTreeFrameType.Component
1097+
&& frame.Component is TreeParameterConsumerComponent<string>);
1098+
var nestedComponentId = componentFrame.ComponentId;
1099+
var nestedComponentDiff = batch.DiffsByComponentId[nestedComponentId].Single();
1100+
1101+
// The nested component was rendered with the correct parameters
1102+
Assert.Collection(nestedComponentDiff.Edits,
1103+
edit =>
1104+
{
1105+
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
1106+
AssertFrame.Text(
1107+
batch.ReferenceFrames[edit.ReferenceFrameIndex],
1108+
"TreeParameter=Hello; RegularParameter=Goodbye");
1109+
});
1110+
}
1111+
1112+
[Fact]
1113+
public void RetainsTreeParametersWhenUpdatingDirectParameters()
1114+
{
1115+
// Arrange
1116+
var renderer = new TestRenderer();
1117+
var regularParameterValue = "Initial value";
1118+
var component = new TestComponent(builder =>
1119+
{
1120+
builder.OpenComponent<Provider<string>>(0);
1121+
builder.AddAttribute(1, "Value", "Hello");
1122+
builder.AddAttribute(2, RenderTreeBuilder.ChildContent, new RenderFragment(childBuilder =>
1123+
{
1124+
childBuilder.OpenComponent<TreeParameterConsumerComponent<string>>(0);
1125+
childBuilder.AddAttribute(1, "RegularParameter", regularParameterValue);
1126+
childBuilder.CloseComponent();
1127+
}));
1128+
builder.CloseComponent();
1129+
});
1130+
1131+
// Act 1: Render in initial state
1132+
var componentId = renderer.AssignRootComponentId(component);
1133+
component.TriggerRender();
1134+
1135+
// Capture the nested component so we can verify the update later
1136+
var firstBatch = renderer.Batches.Single();
1137+
var componentFrame = firstBatch.ReferenceFrames.Single(
1138+
frame => frame.FrameType == RenderTreeFrameType.Component
1139+
&& frame.Component is TreeParameterConsumerComponent<string>);
1140+
var nestedComponentId = componentFrame.ComponentId;
1141+
1142+
// Act 2: Render again with updated regular parameter
1143+
regularParameterValue = "Changed value";
1144+
component.TriggerRender();
1145+
1146+
// Assert
1147+
Assert.Equal(2, renderer.Batches.Count);
1148+
var secondBatch = renderer.Batches[1];
1149+
var nestedComponentDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single();
1150+
1151+
// The nested component was rendered with the correct parameters
1152+
Assert.Collection(nestedComponentDiff.Edits,
1153+
edit =>
1154+
{
1155+
Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
1156+
Assert.Equal(0, edit.ReferenceFrameIndex); // This is the only change
1157+
AssertFrame.Text(secondBatch.ReferenceFrames[0], "TreeParameter=Hello; RegularParameter=Changed value");
1158+
});
1159+
}
1160+
10741161
private class NoOpRenderer : Renderer
10751162
{
10761163
public NoOpRenderer() : base(new TestServiceProvider())
@@ -1331,23 +1418,14 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
13311418
}
13321419
}
13331420

1334-
private class AncestryComponent : AutoRenderComponent
1421+
class TreeParameterConsumerComponent<T> : AutoRenderComponent
13351422
{
1336-
[Parameter] public int NumDescendants { get; private set; }
1423+
[Parameter(FromTree = true)] T TreeParameter { get; set; }
1424+
[Parameter] string RegularParameter { get; set; }
13371425

13381426
protected override void BuildRenderTree(RenderTreeBuilder builder)
13391427
{
1340-
// Recursively renders more of the same until NumDescendants == 0
1341-
if (NumDescendants > 0)
1342-
{
1343-
builder.OpenComponent<AncestryComponent>(0);
1344-
builder.AddAttribute(1, nameof(NumDescendants), NumDescendants - 1);
1345-
builder.CloseComponent();
1346-
}
1347-
else
1348-
{
1349-
builder.AddContent(1, "I'm the final descendant");
1350-
}
1428+
builder.AddContent(0, $"TreeParameter={TreeParameter}; RegularParameter={RegularParameter}");
13511429
}
13521430
}
13531431
}

0 commit comments

Comments
 (0)