In RazorCompiler, support components with children

This commit is contained in:
Steve Sanderson 2018-02-21 17:54:01 +00:00
parent d67bf63864
commit 95023c0300
4 changed files with 39 additions and 12 deletions

View File

@ -220,17 +220,17 @@ namespace Microsoft.AspNetCore.Blazor.Razor
case HtmlTokenType.EndTag:
{
var nextTag = nextToken.AsTag();
var isComponent = false;
var tagNameOriginalCase = GetTagNameWithOriginalCase(originalHtmlContent, nextTag);
var isComponent = TryGetComponentTypeNameFromTagName(tagNameOriginalCase, out var componentTypeName);
if (nextToken.Type == HtmlTokenType.StartTag)
{
var tagNameOriginalCase = GetTagNameWithOriginalCase(originalHtmlContent, nextTag);
if (TryGetComponentTypeNameFromTagName(tagNameOriginalCase, out var componentTypeName))
if (isComponent)
{
codeWriter
.WriteStartMethodInvocation($"{builderVarName}.{nameof(RenderTreeBuilder.OpenComponent)}<{componentTypeName}>")
.Write((_sourceSequence++).ToString())
.WriteEndMethodInvocation();
isComponent = true;
}
else
{
@ -304,7 +304,10 @@ namespace Microsoft.AspNetCore.Blazor.Razor
}
private static string GetTagNameWithOriginalCase(string document, HtmlTagToken tagToken)
=> document.Substring(tagToken.Position.Position, tagToken.Name.Length);
{
var offset = tagToken.Type == HtmlTokenType.EndTag ? 1 : 0; // For end tags, skip the '/'
return document.Substring(tagToken.Position.Position + offset, tagToken.Name.Length);
}
private bool TryGetComponentTypeNameFromTagName(string tagName, out string componentTypeName)
{

View File

@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
// Assert
Assert.Collection(frames,
frame => AssertFrame.Component<TestComponent>(frame, 0));
frame => AssertFrame.Component<TestComponent>(frame, 1, 0));
}
[Fact]
@ -398,7 +398,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
// This problem will probably go away on its own when we have new component
// tooling.
Assert.Collection(frames,
frame => AssertFrame.Component<TestComponent>(frame, 0),
frame => AssertFrame.Component<TestComponent>(frame, 4, 0),
frame => AssertFrame.Attribute(frame, "intproperty", "123", 1),
frame => AssertFrame.Attribute(frame, "stringproperty", "My string", 2),
frame =>
@ -408,6 +408,26 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
});
}
[Fact]
public void CanIncludeChildrenInComponents()
{
// Arrange/Act
var testComponentTypeName = typeof(TestComponent).FullName.Replace('+', '.');
var component = CompileToComponent($"<c:{testComponentTypeName} attr=\"abc\">" +
$"Some text" +
$"<some-child a='1'>Nested text</some-child>" +
$"</c:{testComponentTypeName}>");
var frames = GetRenderTree(component);
Assert.Collection(frames,
frame => AssertFrame.Component<TestComponent>(frame, 6, 0),
frame => AssertFrame.Attribute(frame, "attr", "abc", 1),
frame => AssertFrame.Text(frame, "Some text", 2),
frame => AssertFrame.Element(frame, "some-child", 3, 3),
frame => AssertFrame.Attribute(frame, "a", "1", 4),
frame => AssertFrame.Text(frame, "Nested text", 5));
}
[Fact]
public void ComponentsDoNotHaveLayoutAttributeByDefault()
{

View File

@ -739,8 +739,8 @@ namespace Microsoft.AspNetCore.Blazor.Test
Assert.Equal(1, entry.ReferenceFrameIndex);
},
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
AssertFrame.ComponentWithInstance<FakeComponent>(renderBatch.ReferenceFrames.Array[0], 0, 12);
AssertFrame.ComponentWithInstance<FakeComponent2>(renderBatch.ReferenceFrames.Array[1], 1, 13);
AssertFrame.ComponentWithInstance<FakeComponent>(renderBatch.ReferenceFrames.Array[0], 0, null, 12);
AssertFrame.ComponentWithInstance<FakeComponent2>(renderBatch.ReferenceFrames.Array[1], 1, null, 13);
}
[Fact]

View File

@ -58,16 +58,20 @@ namespace Microsoft.AspNetCore.Blazor.Test.Helpers
Assert.Equal(attributeValue, frame.AttributeValue);
}
public static void Component<T>(RenderTreeFrame frame, int? sequence = null) where T : IComponent
public static void Component<T>(RenderTreeFrame frame, int? subtreeLength = null, int? sequence = null) where T : IComponent
{
Assert.Equal(RenderTreeFrameType.Component, frame.FrameType);
Assert.Equal(typeof(T), frame.ComponentType);
if (subtreeLength.HasValue)
{
Assert.Equal(subtreeLength.Value, frame.ComponentSubtreeLength);
}
AssertFrame.Sequence(frame, sequence);
}
public static void ComponentWithInstance<T>(RenderTreeFrame frame, int componentId, int? sequence = null) where T : IComponent
public static void ComponentWithInstance<T>(RenderTreeFrame frame, int componentId, int? subtreeLength = null, int? sequence = null) where T : IComponent
{
AssertFrame.Component<T>(frame, sequence);
AssertFrame.Component<T>(frame, subtreeLength, sequence);
Assert.IsType<T>(frame.Component);
Assert.Equal(componentId, frame.ComponentId);
}