In RazorCompiler, support attributes whose values are C# code blocks (treated as event handlers)

This commit is contained in:
Steve Sanderson 2018-01-16 16:58:47 +00:00
parent 5949045319
commit 7cd5228b7f
3 changed files with 52 additions and 12 deletions

View File

@ -76,7 +76,17 @@ namespace Microsoft.Blazor.Build.Core.RazorCompilation.Engine
public override void WriteCSharpCodeAttributeValue(CodeRenderingContext context, CSharpCodeAttributeValueIntermediateNode node)
{
throw new System.NotImplementedException(nameof(WriteCSharpCodeAttributeValue));
if (_currentAttributeValues == null)
{
throw new InvalidOperationException($"Invoked {nameof(WriteCSharpCodeAttributeValue)} while {nameof(_currentAttributeValues)} was null.");
}
// For attributes like "onsomeevent=@{ /* some C# code */ }", we treat it as if you
// wrote "onsomeevent=@(_ => { /* some C# code */ })" because then it works as an
// event handler and is a reasonable syntax for that.
var innerCSharp = (IntermediateToken)node.Children.Single();
innerCSharp.Content = $"_ => {{ {innerCSharp.Content} }}";
_currentAttributeValues.Add(innerCSharp);
}
public override void WriteCSharpExpression(CodeRenderingContext context, CSharpExpressionIntermediateNode node)

View File

@ -236,18 +236,53 @@ namespace Microsoft.Blazor.Build.Test
{
// Arrange/Act
var component = CompileToComponent(
"<elem attr=@MyHandleEvent />"
+ @"@functions {
void MyHandleEvent(Microsoft.Blazor.RenderTree.UIEventArgs eventArgs) {}
}");
@"<elem attr=@MyHandleEvent />
@functions {
public bool HandlerWasCalled { get; set; } = false;
void MyHandleEvent(Microsoft.Blazor.RenderTree.UIEventArgs eventArgs)
{
HandlerWasCalled = true;
}
}");
var handlerWasCalledProperty = component.GetType().GetProperty("HandlerWasCalled");
// Assert
Assert.Collection(GetRenderTree(component),
Assert.False((bool)handlerWasCalledProperty.GetValue(component));
Assert.Collection(GetRenderTree(component).Where(NotWhitespace),
node => AssertNode.Element(node, "elem", 1),
node =>
{
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
Assert.NotNull(node.AttributeEventHandlerValue);
node.AttributeEventHandlerValue(null);
Assert.True((bool)handlerWasCalledProperty.GetValue(component));
});
}
[Fact]
public void SupportsAttributesWithCSharpCodeBlockValues()
{
// Arrange/Act
var component = CompileToComponent(
@"<elem attr=@{ DidInvokeCode = true; } />
@functions {
public bool DidInvokeCode { get; set; } = false;
}");
var didInvokeCodeProperty = component.GetType().GetProperty("DidInvokeCode");
// Assert
Assert.False((bool)didInvokeCodeProperty.GetValue(component));
Assert.Collection(GetRenderTree(component).Where(NotWhitespace),
node => AssertNode.Element(node, "elem", 1),
node =>
{
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
Assert.NotNull(node.AttributeEventHandlerValue);
node.AttributeEventHandlerValue(null);
Assert.True((bool)didInvokeCodeProperty.GetValue(component));
});
}

View File

@ -1,12 +1,7 @@
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button onclick=@OnButtonClicked>Click me</button>
<button onclick=@{ currentCount++; }>Click me</button>
@functions {
int currentCount = 0;
void OnButtonClicked(Microsoft.Blazor.RenderTree.UIEventArgs eventArgs)
{
currentCount++;
}
}