Skip to content

Commit

Permalink
Make InputBase use EventCallback for ValueChanged (dotnet#7915)
Browse files Browse the repository at this point in the history
* Make InputBase use EventCallback for ValueChanged

... so that the host component gets re-rendered automatically after each value change (like when binding to DOM elements).

* Improve E2E test code

... so that the host component gets re-rendered automatically after each value change (like when binding to DOM elements).
  • Loading branch information
SteveSandersonMS authored Feb 25, 2019
1 parent 3c558b2 commit 61098b6
Showing 4 changed files with 26 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ public abstract class InputBase<T> : ComponentBase
/// <summary>
/// Gets or sets a callback that updates the bound value.
/// </summary>
[Parameter] Action<T> ValueChanged { get; set; }
[Parameter] EventCallback<T> ValueChanged { get; set; }

/// <summary>
/// Gets or sets an expression that identifies the bound value.
@@ -71,7 +71,7 @@ protected T CurrentValue
if (hasChanged)
{
Value = value;
ValueChanged?.Invoke(value);
_ = ValueChanged.InvokeAsync(value);
EditContext.NotifyFieldChanged(FieldIdentifier);
}
}
3 changes: 2 additions & 1 deletion src/Components/Components/test/Forms/InputBaseTest.cs
Original file line number Diff line number Diff line change
@@ -459,7 +459,8 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
{
childBuilder.OpenComponent<TComponent>(0);
childBuilder.AddAttribute(0, "Value", Value);
childBuilder.AddAttribute(1, "ValueChanged", ValueChanged);
childBuilder.AddAttribute(1, "ValueChanged",
EventCallback.Factory.Create(this, ValueChanged));
childBuilder.AddAttribute(2, "ValueExpression", ValueExpression);
childBuilder.AddAttribute(3, nameof(Id), Id);
childBuilder.AddAttribute(4, nameof(Class), Class);
21 changes: 21 additions & 0 deletions src/Components/test/E2ETest/Tests/FormsTest.cs
Original file line number Diff line number Diff line change
@@ -316,6 +316,27 @@ public void ValidationMessageDisplaysMessagesForField()
WaitAssert.Empty(emailMessagesAccessor);
}

[Fact]
public void InputComponentsCauseContainerToRerenderOnChange()
{
var appElement = MountTestComponent<TypicalValidationComponent>();
var ticketClassInput = new SelectElement(appElement.FindElement(By.ClassName("ticket-class")).FindElement(By.TagName("select")));
var selectedTicketClassDisplay = appElement.FindElement(By.Id("selected-ticket-class"));
var messagesAccessor = CreateValidationMessagesAccessor(appElement);

// Shows initial state
WaitAssert.Equal("Economy", () => selectedTicketClassDisplay.Text);

// Refreshes on edit
ticketClassInput.SelectByValue("Premium");
WaitAssert.Equal("Premium", () => selectedTicketClassDisplay.Text);

// Leaves previous value unchanged if new entry is unparseable
ticketClassInput.SelectByText("(select)");
WaitAssert.Equal(new[] { "The TicketClass field is not valid." }, messagesAccessor);
WaitAssert.Equal("Premium", () => selectedTicketClassDisplay.Text);
}

private Func<string[]> CreateValidationMessagesAccessor(IWebElement appElement)
{
return () => appElement.FindElements(By.ClassName("validation-message"))
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
<option value="@TicketClass.Premium">Premium class</option>
<option value="@TicketClass.First">First class</option>
</InputSelect>
<span id="selected-ticket-class">@person.TicketClass</span>
</p>
<p class="accepts-terms">
Accepts terms: <InputCheckbox bind-Value="@person.AcceptsTerms" />

0 comments on commit 61098b6

Please sign in to comment.